Source:NetHack 1.4f/save.c
Revision as of 01:35, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 1.4f/save.c moved to Source:NetHack 1.4f/save.c: Robot: moved page)
Below is the full text to save.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/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.4 87/08/08 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. #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. u.uluck--; /* 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. if(tmp != getuid()) { /* strange ... */ 185. (void) close(fd); 186. (void) unlink(SAVEF); 187. puts("Saved game was not yours."); 188. restoring = FALSE; 189. return(0); 190. } 191. mread(fd, (char *) &flags, sizeof(struct flag)); 192. #ifdef DGK 193. /* Some config file OPTIONS take precedence over those in save file. 194. */ 195. flags.rawio = oldflags.rawio; 196. flags.DECRainbow = oldflags.DECRainbow; 197. flags.IBMBIOS = oldflags.IBMBIOS; 198. #endif 199. mread(fd, (char *) &dlevel, sizeof dlevel); 200. mread(fd, (char *) &maxdlevel, sizeof maxdlevel); 201. mread(fd, (char *) &moves, sizeof moves); 202. mread(fd, (char *) &u, sizeof(struct you)); 203. #ifdef SPELLS 204. mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 205. #endif 206. if(u.ustuck) 207. mread(fd, (char *) &mid, sizeof mid); 208. mread(fd, (char *) pl_character, sizeof pl_character); 209. mread(fd, (char *) genocided, sizeof genocided); 210. mread(fd, (char *) fut_geno, sizeof fut_geno); 211. #ifdef HARD 212. mread(fd, (char *) &pm_wizard, sizeof(struct permonst)); 213. #endif 214. restnames(fd); 215. #ifdef DGK 216. msmsg("\n"); 217. cl_end(); 218. msmsg("You got as far as level %d%s.\n", maxdlevel, 219. flags.debug ? " in WIZARD mode" : ""); 220. cl_end(); 221. msmsg("Restoring: "); 222. #endif 223. while(1) { 224. if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp) 225. break; 226. getlev(fd, 0, tmp); 227. glo(tmp); 228. #ifdef DGK 229. msmsg("."); 230. nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); 231. #else 232. nfd = creat(lock, FMASK); 233. #endif 234. if (nfd < 0) panic("Cannot open temp file %s!\n", lock); 235. #ifdef DGK 236. if (!savelev(nfd, tmp, COUNT | WRITE)) { 237. 238. /* The savelev can't proceed because the size required 239. * is greater than the available disk space. 240. */ 241. msmsg("\nNot enough space on `%s' to restore your game.\n", 242. levels); 243. 244. /* Remove levels and bones that may have been created. 245. */ 246. (void) close(nfd); 247. eraseall(levels, alllevels); 248. eraseall(levels, allbones); 249. 250. /* Perhaps the person would like to play without a 251. * RAMdisk. 252. */ 253. if (ramdisk) { 254. /* PlaywoRAMdisk may not return, but if it does 255. * it is certain that ramdisk will be 0. 256. */ 257. playwoRAMdisk(); 258. (void) lseek(fd, 0L, 0); /* Rewind save file */ 259. return dorecover(fd); /* and try again */ 260. } else { 261. msmsg("Be seeing you ...\n"); 262. exit(0); 263. } 264. } 265. #else 266. savelev(nfd,tmp); 267. #endif 268. (void) close(nfd); 269. } 270. (void) lseek(fd, 0L, 0); 271. getlev(fd, 0, 0); 272. (void) close(fd); 273. (void) unlink(SAVEF); 274. if(Punished) { 275. for(otmp = fobj; otmp; otmp = otmp->nobj) 276. if(otmp->olet == CHAIN_SYM) goto chainfnd; 277. panic("Cannot find the iron chain?"); 278. chainfnd: 279. uchain = otmp; 280. if(!uball){ 281. for(otmp = fobj; otmp; otmp = otmp->nobj) 282. if(otmp->olet == BALL_SYM && otmp->spe) 283. goto ballfnd; 284. panic("Cannot find the iron ball?"); 285. ballfnd: 286. uball = otmp; 287. } 288. } 289. if(u.ustuck) { 290. register struct monst *mtmp; 291. 292. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 293. if(mtmp->m_id == mid) goto monfnd; 294. panic("Cannot find the monster ustuck."); 295. monfnd: 296. u.ustuck = mtmp; 297. } 298. #ifndef QUEST 299. setsee(); /* only to recompute seelx etc. - these weren't saved */ 300. #endif 301. #ifdef DGK 302. gameDiskPrompt(); 303. #endif 304. docrt(); 305. restoring = FALSE; 306. return(1); 307. } 308. 309. struct obj * 310. restobjchn(fd) 311. register fd; 312. { 313. register struct obj *otmp, *otmp2; 314. register struct obj *first = 0; 315. int xl; 316. #ifdef lint 317. /* suppress "used before set" warning from lint */ 318. otmp2 = 0; 319. #endif 320. while(1) { 321. mread(fd, (char *) &xl, sizeof(xl)); 322. if(xl == -1) break; 323. otmp = newobj(xl); 324. if(!first) first = otmp; 325. else otmp2->nobj = otmp; 326. mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj)); 327. if(!otmp->o_id) otmp->o_id = flags.ident++; 328. otmp2 = otmp; 329. } 330. if(first && otmp2->nobj){ 331. impossible("Restobjchn: error reading objchn."); 332. otmp2->nobj = 0; 333. } 334. return(first); 335. } 336. #ifdef MSDOS 337. struct monst * 338. restmonchn(fd) 339. register fd; 340. { 341. register struct monst *mtmp, *mtmp2; 342. register struct monst *first = 0; 343. int xl; 344. int monsindex; 345. extern struct permonst li_dog, dog, la_dog; 346. #ifdef KAA 347. extern struct permonst hell_hound; 348. # ifdef HARD 349. extern struct permonst d_lord, d_prince; 350. # endif 351. #endif 352. 353. #ifdef lint 354. /* suppress "used before set" warning from lint */ 355. mtmp2 = 0; 356. #endif /* lint /**/ 357. while(1) { 358. mread(fd, (char *) &xl, sizeof(xl)); 359. if(xl == -1) break; 360. mtmp = newmonst(xl); 361. if(!first) first = mtmp; 362. else mtmp2->nmon = mtmp; 363. mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 364. if(!mtmp->m_id) 365. mtmp->m_id = flags.ident++; 366. monsindex = *((int *)&mtmp->data); 367. if (monsindex == -1) /* Special fake index */ 368. mtmp->data = &li_dog; 369. else if (monsindex == -2) /* Special fake index */ 370. mtmp->data = &dog; 371. else if (monsindex == -3) /* Special fake index */ 372. mtmp->data = &la_dog; 373. #ifdef KAA 374. else if (monsindex == -4) 375. mtmp->data = &hell_hound; 376. # ifdef HARD 377. else if (monsindex == -5) 378. mtmp->data = &d_lord; 379. 380. else if (monsindex == -6) 381. mtmp->data = &d_prince; 382. # endif 383. #endif 384. else 385. mtmp->data = &mons[monsindex]; 386. if(mtmp->minvent) 387. mtmp->minvent = restobjchn(fd); 388. mtmp2 = mtmp; 389. } 390. if(first && mtmp2->nmon){ 391. impossible("Restmonchn: error reading monchn."); 392. mtmp2->nmon = 0; 393. } 394. return(first); 395. } 396. #else 397. struct monst * 398. restmonchn(fd) 399. register fd; 400. { 401. register struct monst *mtmp, *mtmp2; 402. register struct monst *first = 0; 403. int xl; 404. 405. struct permonst *monbegin; 406. long differ; 407. 408. mread(fd, (char *)&monbegin, sizeof(monbegin)); 409. differ = (char *)(&mons[0]) - (char *)(monbegin); 410. 411. #ifdef lint 412. /* suppress "used before set" warning from lint */ 413. mtmp2 = 0; 414. #endif 415. while(1) { 416. mread(fd, (char *) &xl, sizeof(xl)); 417. if(xl == -1) break; 418. mtmp = newmonst(xl); 419. if(!first) first = mtmp; 420. else mtmp2->nmon = mtmp; 421. mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst)); 422. if(!mtmp->m_id) 423. mtmp->m_id = flags.ident++; 424. mtmp->data = (struct permonst *) 425. ((char *) mtmp->data + differ); 426. if(mtmp->minvent) 427. mtmp->minvent = restobjchn(fd); 428. mtmp2 = mtmp; 429. } 430. if(first && mtmp2->nmon){ 431. impossible("Restmonchn: error reading monchn."); 432. mtmp2->nmon = 0; 433. } 434. return(first); 435. } 436. #endif