Source:NetHack 3.1.0/save.c
Jump to navigation
Jump to search
Below is the full text to save.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/save.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)save.c 3.1 93/01/07 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "lev.h" 7. 8. #ifndef NO_SIGNAL 9. #include <signal.h> 10. #endif /* !NO_SIGNAL */ 11. #if defined(EXPLORE_MODE) && !defined(LSC) && !defined(O_WRONLY) && !defined(AZTEC_C) 12. #include <fcntl.h> 13. #endif /* EXPLORE_MODE */ 14. 15. boolean hu; /* set during hang-up */ 16. 17. #ifdef MULDGN 18. #include "quest.h" 19. #endif 20. 21. #ifdef MFLOPPY 22. extern struct finfo fileinfo[]; 23. long bytes_counted; 24. static int count_only; 25. #else 26. extern boolean level_exists[]; 27. #endif 28. 29. #ifdef MICRO 30. int dotcnt; /* also used in restore */ 31. #endif 32. 33. #ifdef ZEROCOMP 34. static void FDECL(bputc, (UCHAR_P)); 35. #endif 36. static void FDECL(savelevchn, (int, int)); 37. static void FDECL(savedamage, (int,struct damage *, int)); 38. static void FDECL(saveobjchn, (int,struct obj *, int)); 39. static void FDECL(savemonchn, (int,struct monst *, int)); 40. static void FDECL(savetrapchn, (int,struct trap *, int)); 41. static void FDECL(savegenoinfo, (int)); 42. static void FDECL(savegamestate, (int, int)); 43. #ifdef MFLOPPY 44. static void FDECL(savelev0, (int,XCHAR_P,int)); 45. static boolean NDECL(swapout_oldest); 46. static void FDECL(copyfile, (char *,char *)); 47. #endif /* MFLOPPY */ 48. #ifdef GCC_WARN 49. static long nulls[10]; 50. #else 51. #define nulls nul 52. #endif 53. 54. int 55. dosave() 56. { 57. clear_nhwindow(WIN_MESSAGE); 58. if(yn("Really save?") == 'n') { 59. clear_nhwindow(WIN_MESSAGE); 60. if(multi > 0) nomul(0); 61. } else { 62. clear_nhwindow(WIN_MESSAGE); 63. pline("Saving..."); 64. mark_synch(); /* flush output */ 65. hu = FALSE; 66. if(dosave0()) { 67. /* make sure they see the Saving message */ 68. display_nhwindow(WIN_MESSAGE, TRUE); 69. exit_nhwindows("Be seeing you..."); 70. terminate(0); 71. } else (void)doredraw(); 72. } 73. return 0; 74. } 75. 76. #ifndef NOSAVEONHANGUP 77. int 78. hangup() { 79. if(!hu) { 80. hu = TRUE; 81. (void) dosave0(); 82. # ifndef VMS 83. terminate(1); 84. # endif 85. } 86. return 0; 87. } 88. #endif 89. 90. /* returns 1 if save successful */ 91. int 92. dosave0() 93. { 94. register int fd, ofd; 95. xchar ltmp; 96. #ifdef MFLOPPY 97. long fds, needed; 98. #endif 99. 100. if (!SAVEF[0]) 101. return 0; 102. 103. #if defined(UNIX) || defined(VMS) 104. (void) signal(SIGHUP, SIG_IGN); 105. #endif 106. #ifndef NO_SIGNAL 107. (void) signal(SIGINT, SIG_IGN); 108. #endif 109. 110. #if defined(MICRO) && defined(MFLOPPY) 111. if(!hu && !saveDiskPrompt(0)) return 0; 112. #endif 113. 114. #ifdef EXPLORE_MODE 115. if(!hu && flags.window_inited) { 116. fd = open_savefile(); 117. if (fd > 0) { 118. (void) close(fd); 119. clear_nhwindow(WIN_MESSAGE); 120. pline("There seems to be an old save file."); 121. if (yn("Overwrite the old file?") == 'n') return 0; 122. } 123. } 124. #endif 125. 126. fd = create_savefile(); 127. 128. if(fd < 0) { 129. if(!hu) pline("Cannot open save file."); 130. (void) delete_savefile(); /* ab@unido */ 131. return(0); 132. } 133. if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ 134. change_luck(-1); /* and unido!ab */ 135. if(flags.friday13) 136. change_luck(1); 137. if(flags.window_inited) 138. clear_nhwindow(WIN_MESSAGE); 139. 140. #ifdef MFLOPPY 141. if(!hu) { 142. dotcnt = 0; 143. curs(WIN_MAP, 1, 1); 144. putstr(WIN_MAP, 0, "Saving:"); 145. } 146. /* make sure there is enough disk space */ 147. savelev(fd, ledger_no(&u.uz), COUNT_SAVE); 148. savegamestate(fd, COUNT_SAVE); 149. needed = bytes_counted; 150. for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) 151. if (ltmp != ledger_no(&u.uz) && fileinfo[ltmp].where) 152. needed += fileinfo[ltmp].size + (sizeof ltmp); 153. # ifdef AMIGA 154. needed+=ami_wbench_iconsize(SAVEF); 155. # endif 156. fds = freediskspace(SAVEF); 157. if(needed > fds) { 158. if(!hu) { 159. pline("There is insufficient space on SAVE disk."); 160. pline("Require %ld bytes but only have %ld.", needed, fds); 161. } 162. flushout(); 163. (void) close(fd); 164. (void) delete_savefile(); 165. return 0; 166. } 167. #endif /* MFLOPPY */ 168. 169. bufon(fd); 170. savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE); 171. savegamestate(fd, WRITE_SAVE | FREE_SAVE); 172. 173. for(ltmp = (xchar)1; ltmp <= maxledgerno(); ltmp++) { 174. if (ltmp == ledger_no(&u.uz)) continue; 175. #ifdef MFLOPPY 176. if (!fileinfo[ltmp].where) continue; 177. #else 178. if(!level_exists[ltmp]) continue; 179. #endif 180. #ifdef MICRO 181. if(!hu) { 182. curs(WIN_MAP, 8 + dotcnt++, 1); 183. putstr(WIN_MAP, 0, "."); 184. } 185. #endif 186. ofd = open_levelfile(ltmp); 187. if(ofd < 0) { 188. if(!hu) pline("Cannot read level %d.", ltmp); 189. (void) close(fd); 190. (void) delete_savefile(); 191. if(!hu) done(TRICKED); 192. return(0); 193. } 194. minit(); /* ZEROCOMP */ 195. getlev(ofd, hackpid, ltmp, FALSE); 196. (void) close(ofd); 197. bwrite(fd, (genericptr_t) <mp, sizeof ltmp); /* level number*/ 198. savelev(fd, ltmp, WRITE_SAVE | FREE_SAVE); /* actual level*/ 199. delete_levelfile(ltmp); 200. } 201. bclose(fd); 202. 203. /* get rid of current level --jgm */ 204. delete_levelfile(ledger_no(&u.uz)); 205. delete_levelfile(0); 206. compress(SAVEF); 207. #ifdef AMIGA 208. ami_wbench_iconwrite(SAVEF); 209. #endif 210. return(1); 211. } 212. 213. static void 214. savegamestate(fd, mode) 215. register int fd, mode; 216. { 217. int tmp; /* not register ! */ 218. 219. #ifdef MFLOPPY 220. count_only = (mode & COUNT_SAVE); 221. #endif 222. saveobjchn(fd, invent, mode); 223. saveobjchn(fd, migrating_objs, mode); 224. savemonchn(fd, migrating_mons, mode); 225. savegenoinfo(fd); 226. tmp = getuid(); 227. bwrite(fd, (genericptr_t) &tmp, sizeof tmp); 228. bwrite(fd, (genericptr_t) &flags, sizeof(struct flag)); 229. bwrite(fd, (genericptr_t) &u, sizeof(struct you)); 230. save_dungeon(fd); 231. bwrite(fd, (genericptr_t) &inv_pos, sizeof inv_pos); 232. savelevchn(fd, mode); 233. bwrite(fd, (genericptr_t) &moves, sizeof moves); 234. bwrite(fd, (genericptr_t) &monstermoves, sizeof monstermoves); 235. #ifdef MULDGN 236. bwrite(fd, (genericptr_t) &quest_status, sizeof(struct q_score)); 237. #endif 238. bwrite(fd, (genericptr_t) spl_book, 239. sizeof(struct spell) * (MAXSPELL + 1)); 240. save_artifacts(fd); 241. save_oracles(fd); 242. if(u.ustuck) 243. bwrite(fd, (genericptr_t) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 244. bwrite(fd, (genericptr_t) pl_character, sizeof pl_character); 245. #ifdef TUTTI_FRUTTI 246. bwrite(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); 247. bwrite(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit); 248. savefruitchn(fd, mode); 249. #endif 250. savenames(fd); 251. save_waterlevel(fd); 252. bflush(fd); 253. } 254. 255. #ifdef INSURANCE 256. void 257. savestateinlock() 258. { 259. int fd, hpid; 260. static boolean havestate = TRUE; 261. 262. /* When checkpointing is on, the full state needs to be written 263. * on each checkpoint. When checkpointing is off, only the pid 264. * needs to be in the level.0 file, so it does not need to be 265. * constantly rewritten. When checkpointing is turned off during 266. * a game, however, the file has to be rewritten once to truncate 267. * it and avoid restoring from outdated information. 268. * 269. * Restricting havestate to this routine means that an additional 270. * noop pid rewriting will take place on the first "checkpoint" after 271. * the game is started or restored, if checkpointing is off. 272. */ 273. if (flags.ins_chkpt || havestate) { 274. /* save the rest of the current game state in the lock file, 275. * following the original int pid, the current level number, 276. * and the current savefile name, which should not be subject 277. * to any internal compression schemes since they must be 278. * readable by an external utility 279. */ 280. fd = open_levelfile(0); 281. if (fd < 0) { 282. pline("Cannot open level 0."); 283. pline("Probably someone removed it."); 284. done(TRICKED); 285. return; 286. } 287. 288. (void) read(fd, (genericptr_t) &hpid, sizeof(hpid)); 289. if (hackpid != hpid) { 290. pline("Level 0 pid bad!"); 291. done(TRICKED); 292. } 293. (void) close(fd); 294. 295. fd = create_levelfile(0); 296. if (fd < 0) { 297. pline("Cannot rewrite level 0."); 298. done(TRICKED); 299. return; 300. } 301. (void) write(fd, (genericptr_t) &hackpid, sizeof(hackpid)); 302. if (flags.ins_chkpt) { 303. int currlev = ledger_no(&u.uz); 304. 305. (void) write(fd, (genericptr_t) &currlev, sizeof(currlev)); 306. save_savefile_name(fd); 307. bufon(fd); 308. savegamestate(fd, WRITE_SAVE); 309. } 310. bclose(fd); 311. } 312. havestate = flags.ins_chkpt; 313. } 314. #endif 315. 316. #ifdef MFLOPPY 317. boolean 318. savelev(fd, lev, mode) 319. int fd; 320. xchar lev; 321. int mode; 322. { 323. if (mode & COUNT_SAVE) { 324. bytes_counted = 0; 325. savelev0(fd, lev, COUNT_SAVE); 326. while (bytes_counted > freediskspace(levels)) 327. if (!swapout_oldest()) 328. return FALSE; 329. } 330. if (mode & WRITE_SAVE) { 331. bytes_counted = 0; 332. /* mode is WRITE_SAVE and possibly FREE_SAVE */ 333. savelev0(fd, lev, mode); 334. } 335. fileinfo[lev].where = ACTIVE; 336. fileinfo[lev].time = moves; 337. fileinfo[lev].size = bytes_counted; 338. return TRUE; 339. } 340. 341. static void 342. savelev0(fd,lev,mode) 343. #else 344. void 345. savelev(fd,lev,mode) 346. #endif 347. int fd; 348. xchar lev; 349. int mode; 350. { 351. #ifdef TOS 352. short tlev; 353. #endif 354. 355. if(fd < 0) panic("Save on bad file!"); /* impossible */ 356. #ifdef MFLOPPY 357. count_only = (mode & COUNT_SAVE); 358. #else 359. if(lev >= 0 && lev <= maxledgerno()) level_exists[lev] = TRUE; 360. #endif 361. bwrite(fd,(genericptr_t) &hackpid,sizeof(hackpid)); 362. #ifdef TOS 363. tlev=lev; tlev &= 0x00ff; 364. bwrite(fd,(genericptr_t) &tlev,sizeof(tlev)); 365. #else 366. bwrite(fd,(genericptr_t) &lev,sizeof(lev)); 367. #endif 368. #ifdef RLECOMP 369. { 370. /* perform run-length encoding of rm structs */ 371. struct rm *prm, *rgrm; 372. int x, y; 373. uchar match; 374. 375. rgrm = &levl[0][0]; /* start matching at first rm */ 376. match = 0; 377. 378. for (y = 0; y < ROWNO; y++) { 379. for (x = 0; x < COLNO; x++) { 380. prm = &levl[x][y]; 381. if (prm->glyph == rgrm->glyph 382. && prm->typ == rgrm->typ 383. && prm->seen == rgrm->seen 384. && prm->lit == rgrm->lit 385. && prm->doormask == rgrm->doormask 386. && prm->horizontal == rgrm->horizontal 387. && prm->waslit == rgrm->waslit 388. && prm->roomno == rgrm->roomno 389. && prm->edge == rgrm->edge) { 390. match++; 391. if (match > 254) { 392. match = 254; /* undo this match */ 393. goto writeout; 394. } 395. } else { 396. /* the run has been broken, 397. * write out run-length encoding */ 398. writeout: 399. bwrite(fd, (genericptr_t)&match, sizeof(uchar)); 400. bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm)); 401. /* start encoding again. we have at least 1 rm 402. * in the next run, viz. this one. */ 403. match = 1; 404. rgrm = prm; 405. } 406. } 407. } 408. if (match > 0) { 409. bwrite(fd, (genericptr_t)&match, sizeof(uchar)); 410. bwrite(fd, (genericptr_t)rgrm, sizeof(struct rm)); 411. } 412. } 413. #else 414. bwrite(fd,(genericptr_t) levl,sizeof(levl)); 415. #endif /* RLECOMP */ 416. 417. bwrite(fd,(genericptr_t) &monstermoves,sizeof(monstermoves)); 418. bwrite(fd,(genericptr_t) &upstair,sizeof(stairway)); 419. bwrite(fd,(genericptr_t) &dnstair,sizeof(stairway)); 420. bwrite(fd,(genericptr_t) &upladder,sizeof(stairway)); 421. bwrite(fd,(genericptr_t) &dnladder,sizeof(stairway)); 422. bwrite(fd,(genericptr_t) &sstairs,sizeof(stairway)); 423. bwrite(fd,(genericptr_t) &updest,sizeof(dest_area)); 424. bwrite(fd,(genericptr_t) &dndest,sizeof(dest_area)); 425. bwrite(fd,(genericptr_t) &level.flags,sizeof(level.flags)); 426. savemonchn(fd, fmon, mode); 427. save_worm(fd, mode); /* save worm information */ 428. savetrapchn(fd, ftrap, mode); 429. saveobjchn(fd, fobj, mode); 430. saveobjchn(fd, billobjs, mode); 431. 432. save_engravings(fd, mode); 433. save_rooms(fd); 434. bwrite(fd,(genericptr_t) doors,sizeof(doors)); 435. savedamage(fd, level.damagelist, mode); 436. if (mode & FREE_SAVE) { 437. billobjs = 0; 438. ftrap = 0; 439. fmon = 0; 440. fobj = 0; 441. } 442. bflush(fd); 443. } 444. 445. #ifdef ZEROCOMP 446. /* The runs of zero-run compression are flushed after the game state or a 447. * level is written out. This adds a couple bytes to a save file, where 448. * the runs could be mashed together, but it allows gluing together game 449. * state and level files to form a save file, and it means the flushing 450. * does not need to be specifically called for every other time a level 451. * file is written out. 452. */ 453. 454. #define RLESC '\0' /* Leading character for run of LRESC's */ 455. #define flushoutrun(ln) (bputc(RLESC), bputc(ln), ln = -1) 456. 457. #ifndef ZEROCOMP_BUFSIZ 458. #define ZEROCOMP_BUFSIZ BUFSZ 459. #endif 460. static unsigned char NEARDATA outbuf[ZEROCOMP_BUFSIZ]; 461. static unsigned short NEARDATA outbufp = 0; 462. static short NEARDATA outrunlength = -1; 463. static int NEARDATA bwritefd; 464. 465. /*dbg() 466. { 467. if(!hu) printf("outbufp %d outrunlength %d\n", outbufp,outrunlength); 468. }*/ 469. 470. static void 471. bputc(c) 472. unsigned char c; 473. { 474. #ifdef MFLOPPY 475. bytes_counted++; 476. if (count_only) 477. return; 478. #endif 479. if (outbufp >= sizeof outbuf) { 480. (void) write(bwritefd, outbuf, sizeof outbuf); 481. outbufp = 0; 482. } 483. outbuf[outbufp++] = c; 484. } 485. 486. /*ARGSUSED*/ 487. void 488. bufon(fd) 489. int fd; 490. { 491. return; 492. } 493. 494. void 495. bflush(fd) /* flush run and buffer */ 496. register int fd; 497. { 498. bwritefd = fd; 499. if (outrunlength >= 0) { /* flush run */ 500. flushoutrun(outrunlength); 501. } 502. if (outbufp) { 503. #ifdef MFLOPPY 504. if (!count_only) /* flush buffer */ 505. #endif 506. (void) write(fd, outbuf, outbufp); 507. outbufp = 0; 508. } 509. /*printf("bflush()"); getret();*/ 510. } 511. 512. void 513. bwrite(fd, loc, num) 514. register int fd; 515. genericptr_t loc; 516. register unsigned num; 517. { 518. bwritefd = fd; 519. for (; num; num--, (*(char **)&loc)++) { 520. if (*((char *)loc) == RLESC) { /* One more char in run */ 521. if (++outrunlength == 0xFF) { 522. flushoutrun(outrunlength); 523. } 524. } else { /* end of run */ 525. if (outrunlength >= 0) { /* flush run */ 526. flushoutrun(outrunlength); 527. } 528. bputc(*((char *)loc)); 529. } 530. } 531. } 532. 533. void 534. bclose(fd) 535. int fd; 536. { 537. if (outbufp) 538. panic("closing file with buffered data still unwritten"); 539. (void) close(fd); 540. } 541. 542. #else /* ZEROCOMP */ 543. 544. static int bw_fd = -1; 545. static FILE *bw_FILE = 0; 546. 547. void 548. bufon(fd) 549. int fd; 550. { 551. #ifdef UNIX 552. if(bw_fd >= 0) 553. panic("double buffering unexpected"); 554. bw_fd = fd; 555. if((bw_FILE = fdopen(fd, "w")) == 0) 556. panic("buffering of file %d failed", fd); 557. #endif 558. } 559. 560. void 561. bflush(fd) 562. int fd; 563. { 564. #ifdef UNIX 565. if(fd == bw_fd) { 566. if(fflush(bw_FILE) == EOF) 567. panic("flush of savefile failed!"); 568. } 569. #endif 570. return; 571. } 572. 573. void 574. bwrite(fd,loc,num) 575. register int fd; 576. register genericptr_t loc; 577. register unsigned num; 578. { 579. #ifdef MFLOPPY 580. bytes_counted += num; 581. if (!count_only) 582. #endif 583. { 584. #ifdef UNIX 585. if(fd != bw_fd) 586. panic("unbuffered write to fd %d (!= %d)", fd, bw_fd); 587. 588. if(fwrite(loc, (int)num, 1, bw_FILE) != 1) 589. /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ 590. #else 591. # if defined(BSD) || defined(ULTRIX) 592. if(write(fd, loc, (int)num) != (int)num) 593. # else /* e.g. SYSV, __TURBOC__ */ 594. if(write(fd, loc, num) != num) 595. # endif 596. #endif 597. { 598. if(!hu) panic("cannot write %u bytes to file #%d", num, fd); 599. else terminate(1); 600. } 601. } 602. } 603. 604. void 605. bclose(fd) 606. int fd; 607. { 608. bflush(fd); 609. #ifdef UNIX 610. if (fd == bw_fd) { 611. (void) fclose(bw_FILE); 612. bw_fd = -1; 613. bw_FILE = 0; 614. return; 615. } 616. #endif 617. (void) close(fd); 618. } 619. #endif /* ZEROCOMP */ 620. 621. static void 622. savelevchn(fd, mode) 623. register int fd, mode; 624. { 625. int cnt = 0; 626. s_level *tmplev, *tmplev2; 627. 628. for(tmplev = sp_levchn; tmplev; tmplev = tmplev->next) cnt++; 629. bwrite(fd, (genericptr_t) &cnt, sizeof(int)); 630. 631. for(tmplev = sp_levchn; tmplev; tmplev = tmplev2) { 632. 633. tmplev2 = tmplev->next; 634. bwrite(fd, (genericptr_t) tmplev, sizeof(s_level)); 635. if (mode & FREE_SAVE) 636. free((genericptr_t) tmplev); 637. } 638. } 639. 640. static void 641. savedamage(fd, damageptr, mode) 642. register int fd, mode; 643. register struct damage *damageptr; 644. { 645. register struct damage *tmp_dam; 646. unsigned int xl = 0; 647. 648. for (tmp_dam = damageptr; tmp_dam; tmp_dam = tmp_dam->next) 649. xl++; 650. bwrite(fd, (genericptr_t) &xl, sizeof(xl)); 651. while (xl--) { 652. bwrite(fd, (genericptr_t) damageptr, sizeof(*damageptr)); 653. tmp_dam = damageptr; 654. damageptr = damageptr->next; 655. if (mode & FREE_SAVE) 656. free((genericptr_t)tmp_dam); 657. } 658. if (mode & FREE_SAVE) 659. level.damagelist = 0; 660. } 661. 662. static void 663. saveobjchn(fd,otmp,mode) 664. register int fd, mode; 665. register struct obj *otmp; 666. { 667. register struct obj *otmp2; 668. unsigned int xl; 669. int minusone = -1; 670. 671. while(otmp) { 672. otmp2 = otmp->nobj; 673. xl = otmp->onamelth; 674. bwrite(fd, (genericptr_t) &xl, sizeof(int)); 675. bwrite(fd, (genericptr_t) otmp, xl + sizeof(struct obj)); 676. 677. if (Is_container(otmp) || otmp->otyp == STATUE) 678. saveobjchn(fd,otmp->cobj,mode); 679. if (mode & FREE_SAVE) 680. dealloc_obj(otmp); 681. otmp = otmp2; 682. } 683. bwrite(fd, (genericptr_t) &minusone, sizeof(int)); 684. } 685. 686. static void 687. savemonchn(fd,mtmp,mode) 688. register int fd, mode; 689. register struct monst *mtmp; 690. { 691. register struct monst *mtmp2; 692. unsigned int xl; 693. int minusone = -1; 694. struct permonst *monbegin = &mons[0]; 695. 696. bwrite(fd, (genericptr_t) &monbegin, sizeof(monbegin)); 697. 698. while(mtmp) { 699. mtmp2 = mtmp->nmon; 700. #ifdef MUSE 701. if (mtmp->mw && mtmp->mw != mtmp->minvent) sort_mwep(mtmp); 702. #endif 703. xl = mtmp->mxlth + mtmp->mnamelth; 704. bwrite(fd, (genericptr_t) &xl, sizeof(int)); 705. bwrite(fd, (genericptr_t) mtmp, xl + sizeof(struct monst)); 706. if(mtmp->minvent) saveobjchn(fd,mtmp->minvent,mode); 707. if (mode & FREE_SAVE) 708. dealloc_monst(mtmp); 709. mtmp = mtmp2; 710. } 711. bwrite(fd, (genericptr_t) &minusone, sizeof(int)); 712. } 713. 714. static void 715. savetrapchn(fd,trap,mode) 716. register int fd,mode; 717. register struct trap *trap; 718. { 719. register struct trap *trap2; 720. while(trap) { 721. trap2 = trap->ntrap; 722. bwrite(fd, (genericptr_t) trap, sizeof(struct trap)); 723. if (mode & FREE_SAVE) 724. dealloc_trap(trap); 725. trap = trap2; 726. } 727. bwrite(fd, (genericptr_t)nulls, sizeof(struct trap)); 728. } 729. 730. #ifdef TUTTI_FRUTTI 731. /* save all the fruit names and ID's; this is used only in saving whole games 732. * (not levels) and in saving bones levels. When saving a bones level, 733. * we only want to save the fruits which exist on the bones level; the bones 734. * level routine marks nonexistent fruits by making the fid negative. 735. */ 736. void 737. savefruitchn(fd, mode) 738. register int fd, mode; 739. { 740. register struct fruit *f2, *f1; 741. 742. f1 = ffruit; 743. while(f1) { 744. f2 = f1->nextf; 745. if (f1->fid >= 0) { 746. bwrite(fd, (genericptr_t) f1, sizeof(struct fruit)); 747. } 748. if (mode & FREE_SAVE) 749. dealloc_fruit(f1); 750. f1 = f2; 751. } 752. bwrite(fd, (genericptr_t)nulls, sizeof(struct fruit)); 753. } 754. #endif 755. 756. static void 757. savegenoinfo(fd) 758. register int fd; 759. { 760. register int i; 761. unsigned genolist[NUMMONS]; 762. 763. for (i = 0; i < NUMMONS; i++) 764. genolist[i] = mons[i].geno; 765. 766. bwrite(fd, (genericptr_t) genolist, sizeof(genolist)); 767. } 768. 769. #ifdef MFLOPPY 770. boolean 771. swapin_file(lev) 772. int lev; 773. { 774. char to[PATHLEN], from[PATHLEN]; 775. 776. Sprintf(from, "%s%s", permbones, alllevels); 777. Sprintf(to, "%s%s", levels, alllevels); 778. set_levelfile_name(from, lev); 779. set_levelfile_name(to, lev); 780. while (fileinfo[lev].size > freediskspace(to)) 781. if (!swapout_oldest()) 782. return FALSE; 783. # ifdef WIZARD 784. if (wizard) { 785. pline("Swapping in `%s'", from); 786. wait_synch(); 787. } 788. # endif 789. copyfile(from, to); 790. (void) unlink(from); 791. fileinfo[lev].where = ACTIVE; 792. return TRUE; 793. } 794. 795. static boolean 796. swapout_oldest() { 797. char to[PATHLEN], from[PATHLEN]; 798. int i, oldest; 799. long oldtime; 800. 801. if (!ramdisk) 802. return FALSE; 803. for (i = 1, oldtime = 0, oldest = 0; i <= maxledgerno(); i++) 804. if (fileinfo[i].where == ACTIVE 805. && (!oldtime || fileinfo[i].time < oldtime)) { 806. oldest = i; 807. oldtime = fileinfo[i].time; 808. } 809. if (!oldest) 810. return FALSE; 811. Sprintf(from, "%s%s", levels, alllevels); 812. Sprintf(to, "%s%s", permbones, alllevels); 813. set_levelfile_name(from, oldest); 814. set_levelfile_name(to, oldest); 815. # ifdef WIZARD 816. if (wizard) { 817. pline("Swapping out `%s'.", from); 818. wait_synch(); 819. } 820. # endif 821. copyfile(from, to); 822. (void) unlink(from); 823. fileinfo[oldest].where = SWAPPED; 824. return TRUE; 825. } 826. 827. static void 828. copyfile(from, to) 829. char *from, *to; 830. { 831. # ifdef TOS 832. 833. if (_copyfile(from, to)) 834. panic("Can't copy %s to %s", from, to); 835. # else 836. char buf[BUFSIZ]; /* this is system interaction, therefore 837. * BUFSIZ instead of NetHack's BUFSZ */ 838. int nfrom, nto, fdfrom, fdto; 839. 840. if ((fdfrom = open(from, O_RDONLY | O_BINARY, FCMASK)) < 0) 841. panic("Can't copy from %s !?", from); 842. if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK)) < 0) 843. panic("Can't copy to %s", to); 844. do { 845. nfrom = read(fdfrom, buf, BUFSIZ); 846. nto = write(fdto, buf, nfrom); 847. if (nto != nfrom) 848. panic("Copyfile failed!"); 849. } while (nfrom == BUFSIZ); 850. (void) close(fdfrom); 851. (void) close(fdto); 852. # endif /* TOS */ 853. } 854. 855. void 856. co_false() /* see comment in bones.c */ 857. { 858. count_only = FALSE; 859. return; 860. } 861. 862. #endif /* MFLOPPY */ 863. 864. /*save.c*/