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