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