abstract
| - Below is the full text to hack.main.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.main.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2. 3. #include 4. #include 5. #include 6. #include "hack.h" 7. 8. extern char *getlogin(); 9. extern char plname[PL_NSIZ], pl_character[PL_CSIZ]; 10. extern char *getenv(); 11. 12. int (*afternmv)(); 13. 14. int done1(); 15. int hangup(); 16. 17. char safelock[] = "safelock"; 18. xchar locknum; /* max num of players */ 19. char *catmore = "/bin/cat"; /* or e.g. /usr/ucb/more */ 20. char SAVEF[PL_NSIZ + 5] = "save/"; 21. char perm[] = "perm"; 22. char *hname; /* name of the game (argv[0] of call) */ 23. char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ 24. 25. extern char *nomovemsg; 26. extern long wailmsg; 27. 28. main(argc,argv) 29. int argc; 30. char *argv[]; 31. { 32. int fd; 33. #ifdef NEWS 34. int nonews = 0; 35. #endif NEWS 36. char *dir; 37. 38. hname = argv[0]; 39. 40. /* 41. * See if we must change directory to the playground. 42. * (Perhaps hack runs suid and playground is inaccessible 43. * for the player.) 44. * The environment variable HACKDIR is overridden by a 45. * -d command line option. 46. */ 47. dir = getenv("HACKDIR"); 48. if(argc > 1 && !strncmp(argv[1], "-d", 2)) { 49. argc--; 50. argv++; 51. dir = argv[0]+2; 52. if(*dir == '=' || *dir == ':') dir++; 53. if(!*dir && argc > 1) { 54. argc--; 55. argv++; 56. dir = argv[0]; 57. } 58. if(!*dir) 59. error("Flag -d must be followed by a directory name."); 60. } 61. 62. /* 63. * Now we know the directory containing 'record' and 64. * may do a prscore(). 65. */ 66. if(argc > 1 && !strncmp(argv[1], "-s", 2)) { 67. if(dir) chdirx(dir); 68. prscore(argc, argv); 69. exit(0); 70. } 71. 72. /* 73. * It seems he really wants to play. Find the creation date of 74. * this game so as to avoid restoring outdated savefiles. 75. */ 76. gethdate(hname); 77. 78. /* 79. * We cannot do chdir earlier, otherwise gethdate will fail. 80. */ 81. if(dir) chdirx(dir); 82. 83. /* 84. * Who am i? Perhaps we should use $USER instead? 85. */ 86. (void) strncpy(plname, getlogin(), sizeof(plname)-1); 87. 88. /* 89. * Process options. 90. */ 91. while(argc > 1 && argv[1][0] == '-'){ 92. argv++; 93. argc--; 94. switch(argv[0][1]){ 95. #ifdef WIZARD 96. case 'w': 97. if(!strcmp(getlogin(), WIZARD)) 98. wizard = TRUE; 99. else printf("Sorry.
"); 100. break; 101. #endif WIZARD 102. #ifdef NEWS 103. case 'n': 104. nonews++; 105. break; 106. #endif NEWS 107. case 'u': 108. if(argv[0][2]) 109. (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); 110. else if(argc > 1) { 111. argc--; 112. argv++; 113. (void) strncpy(plname, argv[0], sizeof(plname)-1); 114. } else 115. printf("Player name expected after -u
"); 116. break; 117. default: 118. printf("Unknown option: %s
", *argv); 119. } 120. } 121. 122. if(argc > 1) 123. locknum = atoi(argv[1]); 124. if(argc > 2) 125. catmore = argv[2]; 126. #ifdef WIZARD 127. if(wizard) (void) strcpy(plname, "wizard"); else 128. #endif WIZARD 129. if(!*plname || !strncmp(plname, "player", 4)) askname(); 130. plnamesuffix(); /* strip suffix from name */ 131. 132. setbuf(stdout,obuf); 133. (void) srand(getpid()); 134. startup(); 135. cls(); 136. (void) signal(SIGHUP, hangup); 137. #ifdef WIZARD 138. if(!wizard) { 139. #endif WIZARD 140. (void) signal(SIGQUIT,SIG_IGN); 141. (void) signal(SIGINT,SIG_IGN); 142. if(locknum) 143. lockcheck(); 144. else 145. (void) strcpy(lock,plname); 146. #ifdef WIZARD 147. } else { 148. register char *sfoo; 149. (void) strcpy(lock,plname); 150. if(sfoo = getenv("MAGIC")) 151. while(*sfoo) { 152. switch(*sfoo++) { 153. case 'n': (void) srand(*sfoo++); 154. break; 155. } 156. } 157. if(sfoo = getenv("GENOCIDED")){ 158. if(*sfoo == '!'){ 159. extern struct permonst mons[CMNUM+2]; 160. extern char genocided[], fut_geno[]; 161. register struct permonst *pm = mons; 162. register char *gp = genocided; 163. 164. while(pm < mons+CMNUM+2){ 165. if(!index(sfoo, pm->mlet)) 166. *gp++ = pm->mlet; 167. pm++; 168. } 169. *gp = 0; 170. } else 171. (void) strcpy(genocided, sfoo); 172. (void) strcpy(fut_geno, genocided); 173. } 174. } 175. #endif WIZARD 176. u.uhp = 1; /* prevent RIP on early quits */ 177. u.ux = FAR; /* prevent nscr() */ 178. (void) strcat(SAVEF,plname); 179. if((fd = open(SAVEF,0)) >= 0 && 180. (uptodate(fd) || unlink(SAVEF) == 666)) { 181. (void) signal(SIGINT,done1); 182. puts("Restoring old save file..."); 183. (void) fflush(stdout); 184. dorecover(fd); 185. flags.move = 0; 186. } else { 187. #ifdef NEWS 188. if(!nonews) 189. if((fd = open(NEWS,0)) >= 0) 190. outnews(fd); 191. #endif NEWS 192. flags.ident = 1; 193. init_objects(); 194. u_init(); 195. (void) signal(SIGINT,done1); 196. glo(1); 197. mklev(); 198. u.ux = xupstair; 199. u.uy = yupstair; 200. (void) inshop(); 201. setsee(); 202. flags.botlx = 1; 203. makedog(); 204. seemons(); 205. docrt(); 206. pickup(); 207. read_engr_at(u.ux,u.uy); /* superfluous ? */ 208. flags.move = 1; 209. flags.cbreak = ON; 210. flags.echo = OFF; 211. } 212. setftty(); 213. #ifdef TRACK 214. initrack(); 215. #endif TRACK 216. for(;;) { 217. if(flags.move) { 218. #ifdef TRACK 219. settrack(); 220. #endif TRACK 221. if(moves%2 == 0 || 222. (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { 223. extern struct monst *makemon(); 224. movemon(); 225. if(!rn2(70)) 226. (void) makemon((struct permonst *)0, 0, 0); 227. } 228. if(Glib) glibr(); 229. timeout(); 230. ++moves; 231. if(u.uhp < 1) { 232. pline("You die..."); 233. done("died"); 234. } 235. if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ 236. wailmsg = moves; 237. if(u.uhp == 1) 238. pline("You hear the wailing of the Banshee..."); 239. else 240. pline("You hear the howling of the CwnAnnwn..."); 241. } 242. if(u.uhp < u.uhpmax) { 243. if(u.ulevel > 9) { 244. if(Regeneration || !(moves%3)) { 245. flags.botl = 1; 246. u.uhp += rnd((int) u.ulevel-9); 247. if(u.uhp > u.uhpmax) 248. u.uhp = u.uhpmax; 249. } 250. } else if(Regeneration || 251. (!(moves%(22-u.ulevel*2)))) { 252. flags.botl = 1; 253. u.uhp++; 254. } 255. } 256. if(Teleportation && !rn2(85)) tele(); 257. if(Searching && multi >= 0) (void) dosearch(); 258. gethungry(); 259. invault(); 260. } 261. if(multi < 0) { 262. if(!++multi){ 263. pline(nomovemsg ? nomovemsg : 264. "You can move again."); 265. nomovemsg = 0; 266. if(afternmv) (*afternmv)(); 267. afternmv = 0; 268. } 269. } 270. flags.move = 1; 271. find_ac(); 272. #ifndef QUEST 273. if(!flags.mv || Blind) 274. #endif QUEST 275. { 276. seeobjs(); 277. seemons(); 278. nscr(); 279. } 280. if(flags.botl || flags.botlx) bot(); 281. if(multi > 0) { 282. #ifdef QUEST 283. if(flags.run >= 4) finddir(); 284. #endif QUEST 285. lookaround(); 286. if(!multi) { /* lookaround may clear multi */ 287. flags.move = 0; 288. continue; 289. } 290. if(flags.mv) { 291. if(multi 292. flags.mv = flags.run = 0; 293. domove(); 294. } else { 295. --multi; 296. rhack(save_cm); 297. } 298. } else if(multi == 0) 299. rhack((char *) 0); 300. } 301. } 302. 303. lockcheck() 304. { 305. extern int errno; 306. register int i, fd; 307. 308. /* we ignore QUIT and INT at this point */ 309. if (link(perm,safelock) == -1) 310. error("Cannot link safelock. (Try again or rm safelock.)"); 311. 312. for(i = 0; i < locknum; i++) { 313. lock[0]= 'a' + i; 314. if((fd = open(lock,0)) == -1) { 315. if(errno == ENOENT) goto gotlock; /* no such file */ 316. (void) unlink(safelock); 317. error("Cannot open %s", lock); 318. } 319. (void) close(fd); 320. } 321. (void) unlink(safelock); 322. error("Too many hacks running now."); 323. gotlock: 324. fd = creat(lock,FMASK); 325. if(fd == -1) { 326. error("cannot creat lock file."); 327. } else { 328. int pid; 329. 330. pid = getpid(); 331. if(write(fd, (char *) &pid, 2) != 2){ 332. error("cannot write lock"); 333. } 334. if(close(fd) == -1){ 335. error("cannot close lock"); 336. } 337. } 338. if(unlink(safelock) == -1){ 339. error("Cannot unlink safelock"); 340. } 341. } 342. 343. /*VARARGS1*/ 344. error(s,a1,a2,a3,a4) char *s,*a1,*a2,*a3,*a4; { 345. printf("Error: "); 346. printf(s,a1,a2,a3,a4); 347. (void) putchar('
'); 348. exit(1); 349. } 350. 351. glo(foo) 352. register foo; 353. { 354. /* construct the string xlock.n */ 355. register char *tf; 356. 357. tf = lock; 358. while(*tf && *tf!='.') tf++; 359. (void) sprintf(tf, ".%d", foo); 360. } 361. 362. /* 363. * plname is filled either by an option (-u Player or -uPlayer) or 364. * explicitly (-w implies wizard) or by askname. 365. * It may still contain a suffix denoting pl_character. 366. */ 367. askname(){ 368. register int c,ct; 369. printf("
Who are you? "); 370. ct = 0; 371. while((c = getchar()) != '
'){ 372. if(c == EOF) error("End of input
"); 373. if(c != '-') 374. if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; 375. if(ct < sizeof(plname)-1) plname[ct++] = c; 376. } 377. plname[ct] = 0; 378. if(ct == 0) askname(); 379. #ifdef QUEST 380. else printf("Hello %s, welcome to quest!
", plname); 381. #else 382. else printf("Hello %s, welcome to hack!
", plname); 383. #endif QUEST 384. } 385. 386. impossible(){ 387. pline("Program in disorder - perhaps you'd better Quit"); 388. } 389. 390. #ifdef NEWS 391. int stopnews; 392. 393. stopnws(){ 394. (void) signal(SIGINT, SIG_IGN); 395. stopnews++; 396. } 397. 398. outnews(fd) int fd; { 399. int (*prevsig)(); 400. char ch; 401. prevsig = signal(SIGINT, stopnws); 402. while(!stopnews && read(fd,&ch,1) == 1) 403. (void) putchar(ch); 404. (void) putchar('
'); 405. (void) fflush(stdout); 406. (void) close(fd); 407. (void) signal(SIGINT, prevsig); 408. /* See whether we will ask TSKCFW: he might have told us already */ 409. if(!stopnews && pl_character[0]) 410. getret(); 411. } 412. #endif NEWS 413. 414. chdirx(dir) char *dir; { 415. if(chdir(dir) < 0) { 416. perror(dir); 417. error("Cannot chdir to %s.", dir); 418. } 419. }
|