Source:NetHack 1.4f/unixmain.c
(Redirected from NetHack 1.4f/unixmain.c)
Jump to navigation
Jump to search
Below is the full text to unixmain.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/unixmain.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
Screenshots and source code from Hack are used under the CWI license.
1. /* SCCS Id: @(#)unixmain.c 1.4 87/08/08 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* main.c - (Unix) version 1.0.3 */ 4. 5. #include <stdio.h> 6. #include <signal.h> 7. #include "hack.h" 8. 9. #ifdef QUEST 10. #define gamename "NetQuest" 11. #else 12. #define gamename "NetHack" 13. #endif 14. 15. extern char *getlogin(), *getenv(); 16. extern char plname[PL_NSIZ], pl_character[PL_CSIZ]; 17. 18. int (*afternmv)(); 19. int (*occupation)(); 20. 21. int done1(); 22. int hangup(); 23. 24. int hackpid; /* current pid */ 25. int locknum; /* max num of players */ 26. #ifdef DEF_PAGER 27. char *catmore; /* default pager */ 28. #endif 29. char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */ 30. char *hname; /* name of the game (argv[0] of call) */ 31. char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ 32. 33. extern char *nomovemsg; 34. extern long wailmsg; 35. 36. main(argc,argv) 37. int argc; 38. char *argv[]; 39. { 40. register int fd; 41. #ifdef CHDIR 42. register char *dir; 43. #endif 44. 45. hname = argv[0]; 46. hackpid = getpid(); 47. 48. #ifdef CHDIR /* otherwise no chdir() */ 49. /* 50. * See if we must change directory to the playground. 51. * (Perhaps hack runs suid and playground is inaccessible 52. * for the player.) 53. * The environment variable HACKDIR is overridden by a 54. * -d command line option (must be the first option given) 55. */ 56. 57. dir = getenv("HACKDIR"); 58. if(argc > 1 && !strncmp(argv[1], "-d", 2)) { 59. argc--; 60. argv++; 61. dir = argv[0]+2; 62. if(*dir == '=' || *dir == ':') dir++; 63. if(!*dir && argc > 1) { 64. argc--; 65. argv++; 66. dir = argv[0]; 67. } 68. if(!*dir) 69. error("Flag -d must be followed by a directory name."); 70. } 71. #endif /* CHDIR /**/ 72. #ifdef GRAPHICS 73. /* Set the default values of the presentation characters */ 74. memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols)); 75. #endif 76. #ifdef HACKOPTIONS 77. initoptions(); 78. #endif 79. whoami(); 80. /* 81. * Now we know the directory containing 'record' and 82. * may do a prscore(). 83. */ 84. if(argc > 1 && !strncmp(argv[1], "-s", 2)) { 85. #ifdef CHDIR 86. chdirx(dir,0); 87. #endif 88. prscore(argc, argv); 89. exit(0); 90. } 91. 92. /* 93. * It seems he really wants to play. 94. * Remember tty modes, to be restored on exit. 95. */ 96. gettty(); 97. setbuf(stdout,obuf); 98. setrandom(); 99. startup(); 100. init_corpses(); /* initialize optional corpse names */ 101. cls(); 102. u.uhp = 1; /* prevent RIP on early quits */ 103. u.ux = FAR; /* prevent nscr() */ 104. (void) signal(SIGHUP, hangup); 105. 106. /* 107. * Find the creation date of this game, 108. * so as to avoid restoring outdated savefiles. 109. */ 110. gethdate(hname); 111. 112. /* 113. * We cannot do chdir earlier, otherwise gethdate will fail. 114. */ 115. #ifdef CHDIR 116. chdirx(dir,1); 117. #endif 118. 119. /* 120. * Process options. 121. */ 122. while(argc > 1 && argv[1][0] == '-'){ 123. argv++; 124. argc--; 125. switch(argv[0][1]){ 126. #ifdef WIZARD 127. case 'D': 128. if(!strcmp(getlogin(), WIZARD)) 129. wizard = TRUE; 130. else 131. printf("Sorry.\n"); 132. break; 133. #endif 134. #ifdef NEWS 135. case 'n': 136. flags.nonews = TRUE; 137. break; 138. #endif 139. case 'u': 140. if(argv[0][2]) 141. (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); 142. else if(argc > 1) { 143. argc--; 144. argv++; 145. (void) strncpy(plname, argv[0], sizeof(plname)-1); 146. } else 147. printf("Player name expected after -u\n"); 148. break; 149. default: 150. /* allow -T for Tourist, etc. */ 151. (void) strncpy(pl_character, argv[0]+1, 152. sizeof(pl_character)-1); 153. 154. /* printf("Unknown option: %s\n", *argv); */ 155. } 156. } 157. 158. if(argc > 1) 159. locknum = atoi(argv[1]); 160. #ifdef MAX_NR_OF_PLAYERS 161. if(!locknum || locknum > MAX_NR_OF_PLAYERS) 162. locknum = MAX_NR_OF_PLAYERS; 163. #endif 164. #ifdef DEF_PAGER 165. if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) 166. catmore = DEF_PAGER; 167. #endif 168. #ifdef MAIL 169. getmailstatus(); 170. #endif 171. #ifdef WIZARD 172. if(wizard) (void) strcpy(plname, "wizard"); else 173. #endif 174. if(!*plname || !strncmp(plname, "player", 4) 175. || !strncmp(plname, "games", 4)) 176. askname(); 177. plnamesuffix(); /* strip suffix from name; calls askname() */ 178. /* again if suffix was whole name */ 179. /* accepts any suffix */ 180. #ifdef WIZARD 181. if(!wizard) { 182. #endif 183. /* 184. * check for multiple games under the same name 185. * (if !locknum) or check max nr of players (otherwise) 186. */ 187. (void) signal(SIGQUIT,SIG_IGN); 188. (void) signal(SIGINT,SIG_IGN); 189. if(!locknum) 190. (void) strcpy(lock,plname); 191. getlock(); /* sets lock if locknum != 0 */ 192. #ifdef WIZARD 193. } else { 194. register char *sfoo; 195. extern char genocided[], fut_geno[]; 196. (void) strcpy(lock,plname); 197. if(sfoo = getenv("MAGIC")) 198. while(*sfoo) { 199. switch(*sfoo++) { 200. case 'n': (void) srand(*sfoo++); 201. break; 202. } 203. } 204. if(sfoo = getenv("GENOCIDED")){ 205. if(*sfoo == '!'){ 206. extern struct permonst mons[CMNUM+2]; 207. register struct permonst *pm = mons; 208. register char *gp = genocided; 209. 210. while(pm < mons+CMNUM+2){ 211. if(!index(sfoo, pm->mlet)) 212. *gp++ = pm->mlet; 213. pm++; 214. } 215. *gp = 0; 216. } else 217. (void) strcpy(genocided, sfoo); 218. (void) strcpy(fut_geno, genocided); 219. } 220. } 221. #endif /* WIZARD /**/ 222. setftty(); 223. (void) sprintf(SAVEF, "save/%d%s", getuid(), plname); 224. regularize(SAVEF+5); /* avoid . or / in name */ 225. if((fd = open(SAVEF,0)) >= 0 && 226. (uptodate(fd) || unlink(SAVEF) == 666)) { 227. (void) signal(SIGINT,done1); 228. pline("Restoring old save file..."); 229. (void) fflush(stdout); 230. if(!dorecover(fd)) 231. goto not_recovered; 232. pline("Hello %s, welcome to %s!", plname, gamename); 233. flags.move = 0; 234. } else { 235. not_recovered: 236. newgame(); 237. /* give welcome message before pickup messages */ 238. pline("Hello %s, welcome to %s!", plname, gamename); 239. 240. pickup(1); 241. read_engr_at(u.ux,u.uy); 242. flags.move = 1; 243. } 244. 245. flags.moonphase = phase_of_the_moon(); 246. if(flags.moonphase == FULL_MOON) { 247. pline("You are lucky! Full moon tonight."); 248. if(!u.uluck) u.uluck++; 249. } else if(flags.moonphase == NEW_MOON) { 250. pline("Be careful! New moon tonight."); 251. } 252. 253. initrack(); 254. 255. for(;;) { 256. if(flags.move) { /* actual time passed */ 257. 258. settrack(); 259. 260. if(moves%2 == 0 || 261. (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { 262. extern struct monst *makemon(); 263. movemon(); 264. if(!rn2(70)) 265. (void) makemon((struct permonst *)0, 0, 0); 266. } 267. if(Glib) glibr(); 268. timeout(); 269. ++moves; 270. #ifdef PRAYERS 271. if (u.ublesscnt) u.ublesscnt--; 272. #endif 273. if(flags.time) flags.botl = 1; 274. #ifdef KAA 275. if(u.mtimedone) 276. if(u.mh < 1) rehumanize(); 277. else 278. #endif 279. if(u.uhp < 1) { 280. pline("You die..."); 281. done("died"); 282. } 283. if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ 284. wailmsg = moves; 285. #ifdef KAA 286. if(index("WEV", pl_character[0])) { 287. if (u.uhp == 1) 288. pline("%s is about to die.", pl_character); 289. else 290. pline("%s, your life force is running out.", 291. pl_character); 292. } else { 293. #endif 294. if(u.uhp == 1) 295. pline("You hear the wailing of the Banshee..."); 296. else 297. pline("You hear the howling of the CwnAnnwn..."); 298. #ifdef KAA 299. } 300. #endif 301. } 302. #ifdef KAA 303. if (u.mtimedone) { 304. if (u.mh < u.mhmax) { 305. if (Regeneration || !(moves%20)) { 306. flags.botl = 1; 307. u.mh++; 308. } 309. } 310. } 311. #endif 312. if(u.uhp < u.uhpmax) { 313. if(u.ulevel > 9) { 314. if(HRegeneration || !(moves%3)) { 315. flags.botl = 1; 316. u.uhp += rnd((int) u.ulevel-9); 317. if(u.uhp > u.uhpmax) 318. u.uhp = u.uhpmax; 319. } 320. } else if(HRegeneration || 321. (!(moves%(22-u.ulevel*2)))) { 322. flags.botl = 1; 323. u.uhp++; 324. } 325. } 326. #ifdef SPELLS 327. if ((u.uen<u.uenmax) && (!(moves%(21-u.ulevel/2)))) { 328. u.uen += rn2(u.ulevel/4 + 1) + 1; 329. if (u.uen > u.uenmax) u.uen = u.uenmax; 330. flags.botl = 1; 331. } 332. #endif 333. if(Teleportation && !rn2(85)) tele(); 334. if(Searching && multi >= 0) (void) dosearch(); 335. gethungry(); 336. invault(); 337. amulet(); 338. #ifdef HARD 339. if (!rn2(4)) u_wipe_engr(rnd(3)); 340. if (u.udemigod) { 341. 342. u.udg_cnt--; 343. if(u.udg_cnt <= 0) { 344. 345. intervene(); 346. u.udg_cnt = rn1(200, 50); 347. } 348. } 349. #endif 350. } 351. if(multi < 0) { 352. if(!++multi){ 353. pline(nomovemsg ? nomovemsg : 354. "You can move again."); 355. nomovemsg = 0; 356. if(afternmv) (*afternmv)(); 357. afternmv = 0; 358. } 359. } 360. 361. find_ac(); 362. #ifndef QUEST 363. if(!flags.mv || Blind) 364. #endif 365. { 366. seeobjs(); 367. seemons(); 368. nscr(); 369. } 370. #ifdef DGK 371. if(flags.time) flags.botl = 1; 372. #endif 373. if(flags.botl || flags.botlx) bot(); 374. 375. flags.move = 1; 376. 377. if(multi >= 0 && occupation) { 378. 379. if (monster_nearby()) 380. stop_occupation(); 381. else if ((*occupation)() == 0) 382. occupation = 0; 383. continue; 384. } 385. 386. if(multi > 0) { 387. #ifdef QUEST 388. if(flags.run >= 4) finddir(); 389. #endif 390. lookaround(); 391. if(!multi) { /* lookaround may clear multi */ 392. flags.move = 0; 393. continue; 394. } 395. if(flags.mv) { 396. if(multi < COLNO && !--multi) 397. flags.mv = flags.run = 0; 398. domove(); 399. } else { 400. --multi; 401. rhack(save_cm); 402. } 403. } else if(multi == 0) { 404. #ifdef MAIL 405. ckmailstatus(); 406. #endif 407. rhack((char *) 0); 408. } 409. if(multi && multi%7 == 0) 410. (void) fflush(stdout); 411. } 412. } 413. 414. glo(foo) 415. register foo; 416. { 417. /* construct the string xlock.n */ 418. register char *tf; 419. 420. tf = lock; 421. while(*tf && *tf != '.') tf++; 422. (void) sprintf(tf, ".%d", foo); 423. } 424. 425. /* 426. * plname is filled either by an option (-u Player or -uPlayer) or 427. * explicitly (-w implies wizard) or by askname. 428. * It may still contain a suffix denoting pl_character. 429. */ 430. askname(){ 431. register int c,ct; 432. printf("\nWho are you? "); 433. (void) fflush(stdout); 434. ct = 0; 435. while((c = getchar()) != '\n'){ 436. if(c == EOF) error("End of input\n"); 437. /* some people get confused when their erase char is not ^H */ 438. if(c == '\010') { 439. if(ct) ct--; 440. continue; 441. } 442. if(c != '-') 443. if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; 444. if(ct < sizeof(plname)-1) plname[ct++] = c; 445. } 446. plname[ct] = 0; 447. if(ct == 0) askname(); 448. } 449. 450. /*VARARGS1*/ 451. impossible(s,x1,x2) 452. register char *s; 453. { 454. pline(s,x1,x2); 455. pline("Program in disorder - perhaps you'd better Quit."); 456. } 457. 458. #ifdef CHDIR 459. static 460. chdirx(dir, wr) 461. char *dir; 462. boolean wr; 463. { 464. 465. # ifdef SECURE 466. if(dir /* User specified directory? */ 467. # ifdef HACKDIR 468. && strcmp(dir, HACKDIR) /* and not the default? */ 469. # endif 470. ) { 471. (void) setuid(getuid()); /* Ron Wessels */ 472. (void) setgid(getgid()); 473. } 474. # endif 475. 476. # ifdef HACKDIR 477. if(dir == NULL) 478. dir = HACKDIR; 479. # endif 480. 481. if(dir && chdir(dir) < 0) { 482. perror(dir); 483. error("Cannot chdir to %s.", dir); 484. } 485. 486. /* warn the player if he cannot write the record file */ 487. /* perhaps we should also test whether . is writable */ 488. /* unfortunately the access systemcall is worthless */ 489. if(wr) { 490. register fd; 491. 492. if(dir == NULL) 493. dir = "."; 494. if((fd = open(RECORD, 2)) < 0) { 495. printf("Warning: cannot write %s/%s", dir, RECORD); 496. getret(); 497. } else 498. (void) close(fd); 499. } 500. } 501. #endif /* CHDIR /**/ 502. 503. stop_occupation() 504. { 505. if(occupation) { 506. pline("You stop %s.", occtxt); 507. occupation = 0; 508. #ifdef REDO 509. multi = 0; 510. pushch(0); 511. #endif 512. } 513. } 514. 515. whoami() { 516. /* 517. * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS 518. * 2. Use $USER or $LOGNAME (if 1. fails) 519. * 3. Use getlogin() (if 2. fails) 520. * The resulting name is overridden by command line options. 521. * If everything fails, or if the resulting name is some generic 522. * account like "games", "play", "player", "hack" then eventually 523. * we'll ask him. 524. * Note that we trust him here; it is possible to play under 525. * somebody else's name. 526. */ 527. register char *s; 528. 529. #ifndef DGKMOD 530. initoptions(); 531. #endif 532. if(!*plname && (s = getenv("USER"))) 533. (void) strncpy(plname, s, sizeof(plname)-1); 534. if(!*plname && (s = getenv("LOGNAME"))) 535. (void) strncpy(plname, s, sizeof(plname)-1); 536. if(!*plname && (s = getlogin())) 537. (void) strncpy(plname, s, sizeof(plname)-1); 538. } 539. 540. newgame() { 541. fobj = fcobj = invent = 0; 542. fmon = fallen_down = 0; 543. ftrap = 0; 544. fgold = 0; 545. flags.ident = 1; 546. init_objects(); 547. u_init(); 548. 549. (void) signal(SIGINT,done1); 550. mklev(); 551. u.ux = xupstair; 552. u.uy = yupstair; 553. (void) inshop(); 554. setsee(); 555. flags.botlx = 1; 556. { 557. register struct monst *mtmp; 558. 559. /* Move the monster from under you or else 560. * makedog() will fail when it calls makemon(). 561. * - ucsfcgl!kneller 562. */ 563. if (mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); 564. } 565. (void) makedog(); 566. seemons(); 567. #ifdef NEWS 568. if(flags.nonews || !readnews()) 569. /* after reading news we did docrt() already */ 570. #endif 571. docrt(); 572. return(0); 573. } 574. 575. #ifdef GENIX 576. jhndist(x1,y1,x2,y2) 577. { 578. int x,y; 579. x=x1-x2; 580. y=y1-y2; 581. return (x*x + y*y); 582. } 583. #endif