Source:NetHack 2.2a/save.c
Revision as of 02:45, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 2.2a/save.c moved to Source:NetHack 2.2a/save.c: Robot: moved page)
Below is the full text to save.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/save.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: @(#)save.c 2.1 87/10/07 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include <signal.h> 5. #include <stdio.h> 6. #include "hack.h" 7. extern char genocided[60]; /* defined in Decl.c */ 8. extern char fut_geno[60]; /* idem */ 9. extern struct permonst pm_wizard; /* since the wizard evolves */ 10. 11. extern char SAVEF[], nul[]; 12. extern char pl_character[PL_CSIZ]; 13. extern long lseek(); 14. extern struct obj *restobjchn(); 15. extern struct monst *restmonchn(); 16. 17. dosave(){ 18. clear_screen(); 19. fflush(stdout); 20. if(dosave0(0)) { 21. settty("Be seeing you ...\n"); 22. exit(0); 23. } 24. #ifdef LINT 25. return(0); 26. #endif 27. } 28. 29. #ifndef NOSAVEONHANGUP 30. hangup(){ 31. (void) dosave0(1); 32. exit(1); 33. } 34. #endif 35. 36. /* returns 1 if save successful */ 37. dosave0(hu) int hu; { 38. register fd, ofd; 39. int tmp; /* not register ! */ 40. #ifdef DGK 41. long fds, needed; 42. extern long bytes_counted; 43. int mode; 44. #endif 45. #ifdef UNIX 46. (void) signal(SIGHUP, SIG_IGN); 47. #endif 48. #ifndef __TURBOC__ 49. (void) signal(SIGINT, SIG_IGN); 50. #endif 51. #ifdef DGK 52. if (!saveDiskPrompt(0)) 53. return 0; 54. fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK); 55. #else 56. fd = creat(SAVEF, FMASK); 57. #endif 58. if(fd < 0) { 59. if(!hu) pline("Cannot open save file. (Continue or Quit)"); 60. (void) unlink(SAVEF); /* ab@unido */ 61. return(0); 62. } 63. if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ 64. u.uluck--; /* and unido!ab */ 65. #ifdef DGKMOD 66. home(); 67. cl_end(); 68. #endif 69. #ifdef DGK 70. msmsg("Saving: "); 71. mode = COUNT; 72. again: 73. savelev(fd, dlevel, mode); 74. /* count_only will be set properly by savelev */ 75. #else 76. savelev(fd,dlevel); 77. #endif 78. saveobjchn(fd, invent); 79. saveobjchn(fd, fcobj); 80. savemonchn(fd, fallen_down); 81. tmp = getuid(); 82. bwrite(fd, (char *) &tmp, sizeof tmp); 83. bwrite(fd, (char *) &flags, sizeof(struct flag)); 84. bwrite(fd, (char *) &dlevel, sizeof dlevel); 85. bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel); 86. bwrite(fd, (char *) &moves, sizeof moves); 87. bwrite(fd, (char *) &u, sizeof(struct you)); 88. #ifdef SPELLS 89. bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 90. #endif 91. if(u.ustuck) 92. bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 93. bwrite(fd, (char *) pl_character, sizeof pl_character); 94. bwrite(fd, (char *) genocided, sizeof genocided); 95. bwrite(fd, (char *) fut_geno, sizeof fut_geno); 96. #ifdef HARD 97. bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst)); 98. #endif 99. savenames(fd); 100. #ifdef DGK 101. if (mode == COUNT) { 102. /* make sure there is enough disk space */ 103. needed = bytes_counted; 104. for (tmp = 1; tmp <= maxdlevel; tmp++) 105. if (tmp != dlevel && fileinfo[tmp].where) 106. needed += fileinfo[tmp].size + (sizeof tmp); 107. fds = freediskspace(SAVEF); 108. if (needed > fds) { 109. pline("There is insufficient space on SAVE disk."); 110. pline("Require %ld bytes but only have %ld.", needed, 111. fds); 112. flushout(); 113. (void) close(fd); 114. (void) unlink(SAVEF); 115. return 0; 116. } 117. mode = WRITE; 118. goto again; 119. } 120. #endif 121. for(tmp = 1; tmp <= maxdlevel; tmp++) { 122. extern int hackpid; 123. #ifdef DGK 124. if (tmp == dlevel || !fileinfo[tmp].where) continue; 125. if (fileinfo[tmp].where != ACTIVE) 126. swapin_file(tmp); 127. #else 128. extern boolean level_exists[]; 129. 130. if(tmp == dlevel || !level_exists[tmp]) continue; 131. #endif 132. glo(tmp); 133. #ifdef DGK 134. msmsg("."); 135. #endif 136. if((ofd = open(lock, 0)) < 0) { 137. if(!hu) pline("Error while saving: cannot read %s.", lock); 138. (void) close(fd); 139. (void) unlink(SAVEF); 140. if(!hu) done("tricked"); 141. return(0); 142. } 143. getlev(ofd, hackpid, tmp); 144. (void) close(ofd); 145. bwrite(fd, (char *) &tmp, sizeof tmp); /* level number */ 146. #ifdef DGK 147. savelev(fd,tmp,WRITE); /* actual level */ 148. #else 149. savelev(fd,tmp); /* actual level */ 150. #endif 151. (void) unlink(lock); 152. } 153. (void) close(fd); 154. glo(dlevel); 155. (void) unlink(lock); /* get rid of current level --jgm */ 156. glo(0); 157. (void) unlink(lock); 158. return(1); 159. } 160. 161. dorecover(fd) 162. register fd; 163. { 164. register nfd; 165. int tmp; /* not a register ! */ 166. unsigned mid; /* idem */ 167. struct obj *otmp; 168. extern boolean restoring; 169. #ifdef DGK 170. struct flag oldflags; 171. 172. oldflags = flags; /* Save flags set in the config file */ 173. #endif 174. restoring = TRUE; 175. getlev(fd, 0, 0); 176. invent = restobjchn(fd); 177. for(otmp = invent; otmp; otmp = otmp->nobj) 178. if(otmp->owornmask) 179. setworn(otmp, otmp->owornmask); 180. fcobj = restobjchn(fd); 181. fallen_down = restmonchn(fd); 182. mread(fd, (char *) &tmp, sizeof tmp); 183. #ifdef WIZARD 184. if(!wizard) 185. #endif 186. if(tmp != getuid()) { /* strange ... */ 187. (void) close(fd); 188. (void) unlink(SAVEF); 189. puts("Saved game was not yours."); 190. restoring = FALSE; 191. return(0); 192. } 193. mread(fd, (char *) &flags, sizeof(struct flag)); 194. #ifdef DGK 195. /* Some config file OPTIONS take precedence over those in save file. 196. */ 197. flags.rawio = oldflags.rawio; 198. flags.DECRainbow = oldflags.DECRainbow; 199. flags.IBMBIOS = oldflags.IBMBIOS; 200. #endif 201. mread(fd, (char *) &dlevel, sizeof dlevel); 202. mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 203. mread(fd, (char *) &moves, sizeof moves); 204. mread(fd, (char *) &u, sizeof(struct you)); 205. #ifdef SPELLS 206. mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 207. #endif 208. if(u.ustuck) 209. mread(fd, (char *) &mid, sizeof mid); 210. mread(fd, (char *) pl_character, sizeof pl_character); 211. mread(fd, (char *) genocided, sizeof genocided); 212. mread(fd, (char *) fut_geno, sizeof fut_geno); 213. #ifdef HARD 214. mread(fd, (char *) &pm_wizard, sizeof(struct permonst)); 215. #endif 216. restnames(fd); 217. #ifdef DGK 218. msmsg("\n"); 219. cl_end(); 220. msmsg("You got as far as level %d%s.\n", maxdlevel, 221. flags.debug ? " in WIZARD mode" : ""); 222. cl_end(); 223. msmsg("Restoring: "); 224. #endif 225. while(1) { 226. if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 227. break; 228. getlev(fd, 0, tmp); 229. glo(tmp); 230. #ifdef DGK 231. msmsg("."); 232. nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); 233. #else 234. nfd = creat(lock, FMASK); 235. #endif 236. if (nfd < 0) panic("Cannot open temp file %s!\n", lock); 237. #ifdef DGK 238. if (!savelev(nfd, tmp, COUNT | WRITE)) { 239. 240. /* The savelev can't proceed because the size required 241. * is greater than the available disk space. 242. */ 243. msmsg("\nNot enough space on `%s' to restore your game.\n", 244. levels); 245. 246. /* Remove levels and bones that may have been created. 247. */ 248. (void) close(nfd); 249. eraseall(levels, alllevels); 250. eraseall(levels, allbones); 251. 252. /* Perhaps the person would like to play without a 253. * RAMdisk. 254. */ 255. if (ramdisk) { 256. /* PlaywoRAMdisk may not return, but if it does 257. * it is certain that ramdisk will be 0. 258. */ 259. playwoRAMdisk(); 260. (void) lseek(fd, 0L, 0); /* Rewind save file */ 261. return dorecover(fd); /* and try again */ 262. } else { 263. msmsg("Be seeing you ...\n"); 264. exit(0); 265. } 266. } 267. #else 268. savelev(nfd,tmp); 269. #endif 270. (void) close(nfd); 271. } 272. (void) lseek(fd, 0L, 0); 273. getlev(fd, 0, 0); 274. (void) close(fd); 275. (void) unlink(SAVEF); 276. if(Punished) { 277. for(otmp = fobj; otmp; otmp = otmp->nobj) 278. if(otmp->olet == CHAIN_SYM) goto chainfnd; 279. panic("Cannot find the iron chain?"); 280. chainfnd: 281. uchain = otmp; 282. if(!uball){ 283. for(otmp = fobj; otmp; otmp = otmp->nobj) 284. if(otmp->olet == BALL_SYM && otmp->spe) 285. goto ballfnd; 286. panic("Cannot find the iron ball?"); 287. ballfnd: 288. uball = otmp; 289. } 290. } 291. if(u.ustuck) { 292. register struct monst *mtmp; 293. 294. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 295. if(mtmp->m_id == mid) goto monfnd; 296. panic("Cannot find the monster ustuck."); 297. monfnd: 298. u.ustuck = mtmp; 299. } 300. #ifndef QUEST 301. setsee(); /* only to recompute seelx etc. - these weren't saved */ 302. #endif 303. #ifdef DGK 304. gameDiskPrompt(); 305. #endif 306. docrt(); 307. restoring = FALSE; 308. return(1); 309. } 310. 311. struct obj * 312. restobjchn(fd) 313. register fd; 314. { 315. register struct obj *otmp, *otmp2; 316. register struct obj *first = 0; 317. int xl; 318. #ifdef LINT 319. /* suppress "used before set" warning from lint */ 320. otmp2 = 0; 321. #endif 322. while(1) { 323. mread(fd, (char *) &xl, sizeof(xl)); 324. if(xl == -1) break; 325. otmp = newobj(xl); 326. if(!first) first = otmp; 327. else otmp2->nobj = otmp; 328. mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 329. if(!otmp->o_id) otmp->o_id = flags.ident++; 330. otmp2 = otmp; 331. } 332. if(first && otmp2->nobj){ 333. impossible("Restobjchn: error reading objchn."); 334. otmp2->nobj = 0; 335. } 336. return(first); 337. } 338. #ifdef MSDOS 339. struct monst * 340. restmonchn(fd) 341. register fd; 342. { 343. register struct monst *mtmp, *mtmp2; 344. register struct monst *first = 0; 345. int xl; 346. int monsindex, mi; 347. extern struct permonst li_dog, dog, la_dog; 348. #ifdef KAA 349. extern struct permonst hell_hound; 350. # ifdef HARD 351. extern struct permonst d_lord, d_prince; 352. # endif 353. # ifdef KJSMODS 354. extern struct permonst pm_guard, pm_ghost, pm_eel; 355. # endif 356. #endif 357. 358. #ifdef lint 359. /* suppress "used before set" warning from lint */ 360. mtmp2 = 0; 361. #endif /* lint /**/ 362. while(1) { 363. mread(fd, (char *) &xl, sizeof(xl)); 364. if(xl == -1) break; 365. mtmp = newmonst(xl); 366. if(!first) first = mtmp; 367. else mtmp2->nmon = mtmp; 368. mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 369. if(!mtmp->m_id) 370. mtmp->m_id = flags.ident++; 371. monsindex = *((int *)&mtmp->data); 372. if (monsindex == (mi = -1)) /* Special fake index */ 373. mtmp->data = &li_dog; 374. else if (monsindex == --mi) /* Special fake index */ 375. mtmp->data = &dog; 376. else if (monsindex == --mi) /* Special fake index */ 377. mtmp->data = &la_dog; 378. #ifdef KAA 379. else if (monsindex == --mi) 380. mtmp->data = &hell_hound; 381. # ifdef HARD 382. else if (monsindex == --mi) 383. mtmp->data = &d_lord; 384. 385. else if (monsindex == --mi) 386. mtmp->data = &d_prince; 387. # endif 388. # ifdef KJSMODS 389. else if (monsindex == --mi) 390. mtmp->data = &pm_guard; 391. 392. else if (monsindex == --mi) 393. mtmp->data = &pm_ghost; 394. 395. else if (monsindex == --mi) 396. mtmp->data = &pm_eel; 397. # endif 398. #endif 399. else 400. mtmp->data = &mons[monsindex]; 401. if(mtmp->minvent) 402. mtmp->minvent = restobjchn(fd); 403. mtmp2 = mtmp; 404. } 405. if(first && mtmp2->nmon){ 406. impossible("Restmonchn: error reading monchn."); 407. mtmp2->nmon = 0; 408. } 409. return(first); 410. } 411. #else 412. struct monst * 413. restmonchn(fd) 414. register fd; 415. { 416. register struct monst *mtmp, *mtmp2; 417. register struct monst *first = 0; 418. int xl; 419. 420. struct permonst *monbegin; 421. long differ; 422. 423. mread(fd, (char *)&monbegin, sizeof(monbegin)); 424. differ = (char *)(&mons[0]) - (char *)(monbegin); 425. 426. #ifdef LINT 427. /* suppress "used before set" warning from lint */ 428. mtmp2 = 0; 429. #endif 430. while(1) { 431. mread(fd, (char *) &xl, sizeof(xl)); 432. if(xl == -1) break; 433. mtmp = newmonst(xl); 434. if(!first) first = mtmp; 435. else mtmp2->nmon = mtmp; 436. mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 437. if(!mtmp->m_id) 438. mtmp->m_id = flags.ident++; 439. mtmp->data = (struct permonst *) 440. ((char *) mtmp->data + differ); 441. if(mtmp->minvent) 442. mtmp->minvent = restobjchn(fd); 443. mtmp2 = mtmp; 444. } 445. if(first && mtmp2->nmon){ 446. impossible("Restmonchn: error reading monchn."); 447. mtmp2->nmon = 0; 448. } 449. return(first); 450. } 451. #endif