abstract
| - 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 1. /* SCCS Id: @(#)save.c 2.1 87/10/07 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include 5. #include 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 ...
"); 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("
"); 219. cl_end(); 220. msmsg("You got as far as level %d%s.
", 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!
", 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("
Not enough space on `%s' to restore your game.
", 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 ...
"); 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
|