Source:NetHack 3.0.0/save.c

Below is the full text to save.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/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	3.0	89/04/13 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    /* block some unused #defines to avoid overloading some cpp's */ 6.   #define MONATTK_H 7.   #include "hack.h"  8.    #include "lev.h"  9. 10.  #ifdef WORM 11.  #include "wseg.h"  12. #endif 13.   14.   #ifndef TOS 15.  #include   16. #endif /* !TOS */ 17.  #ifdef EXPLORE_MODE 18.  #include   19. #endif /* EXPLORE_MODE */ 20.   21.   boolean hu;		/* set during hang-up */ 22.   23.   #if defined(DGK) && !defined(TOS) 24.  struct finfo fileinfo[MAXLEVEL+1]; 25.  long bytes_counted; 26.  int count_only; 27.  #else 28.  boolean level_exists[MAXLEVEL+1]; 29.  #endif 30.   31.   #if defined(DGK) && !defined(TOS) 32.  static void savelev0; 33.  #endif /* DGK && !TOS */ 34.  static void saveobjchn; 35.  static void savemonchn; 36.  static void savegoldchn; 37.  static void savetrapchn; 38.  static void savegenoinfo; 39.  #if defined(DGK) && !defined(TOS) 40.  static boolean swapout_oldest; 41.  static void copyfile; 42.  #endif /* defined(DGK) && !defined(TOS) */ 43.  static void spill_objs; 44.   45.   int 46.  dosave{ 47.  	pline("Really save? ");	/* especially useful if COMPRESS defined */ 48.  	if(yn == 'n') { 49.  		clrlin; 50.  		(void) fflush(stdout); 51.  		if(multi > 0) nomul(0); 52.  	} else { 53.  #ifdef EXPLORE_MODE 54.  		if(!discover) { 55.  	pline("Do you want to create a non-scoring, restartable save file? "); 56.  			if(yn == 'y')  discover = TRUE; 57.  		}  58.   #endif 59.  		clear_screen; 60.  		(void) fflush(stdout); 61.  		hu = FALSE; 62.  		if(dosave0) { 63.  			settty("Be seeing you...\n"); 64.  			exit(0); 65.  		} else (void)doredraw; 66.  	}  67.   	return 0; 68.  }  69.    70.   #ifndef NOSAVEONHANGUP 71.  int 72.  hangup{ 73.  	hu = TRUE; 74.  	(void) dosave0; 75.  	exit(1); 76.  	return 0; 77.  }  78.   #endif 79.   80.   /* returns 1 if save successful */ 81.  int 82.  dosave0 { 83.  	register int fd, ofd; 84.  	int tmp;		/* not register ! */ 85.   	xchar ltmp; 86.  #if defined(DGK) && !defined(TOS) 87.  	long fds, needed; 88.  	int mode; 89.  #endif 90.  #ifdef COMPRESS 91.  	char	cmd[80]; 92.  #endif 93.  #ifdef UNIX 94.  	(void) signal(SIGHUP, SIG_IGN); 95.  #endif 96.  #if !defined(__TURBOC__) && !defined(TOS) 97.  	(void) signal(SIGINT, SIG_IGN); 98.  #endif 99.   100.  #ifdef MSDOS 101. # ifdef DGK 102. 	if(!hu && !saveDiskPrompt(0))	return 0; 103. # endif 104. # ifdef EXPLORE_MODE 105. 	if(!hu) { 106.  107.  	    fd = open(SAVEF, O_RDONLY); 108. 	    if (fd > 0) { 109. 		(void) close(fd); 110. 		clrlin; 111. 		pline("There seems to be an old save file.  Overwrite it? "); 112. 		if (yn == 'n') return 0; 113. 	    }  114.  	}  115.  # endif 116. # ifdef TOS 117. 	fd = creat(SAVEF, FCMASK); 118. # else 119. 	fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); 120. # endif 121. #else /* MSDOS */ 122. # ifdef EXPLORE_MODE 123. 	if(!hu) { 124. 	    fd = open(SAVEF, O_RDONLY); 125. 	    if (fd > 0) { 126. 		(void) close(fd); 127. 		clrlin; 128. 		pline("There seems to be an old save file.  Overwrite it? "); 129. 		if (yn == 'n') return 0; 130. 	    }  131.  	}  132.  # endif 133. 	fd = creat(SAVEF, FCMASK); 134. #endif /* MSDOS */ 135. 	if(fd < 0) { 136. 		if(!hu) pline("Cannot open save file."); 137. 		(void) unlink(SAVEF);		/* ab@unido */ 138. 		return(0); 139. 	}  140.  	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */ 141. 		change_luck(-1);		/* and unido!ab */ 142. 	home; 143. 	cl_end; 144. #if defined(DGK) && !defined(TOS) 145. 	if(!hu) msmsg("Saving: "); 146. 	mode = COUNT; 147. again: 148. 	savelev(fd, dlevel, mode); 149. 	/* count_only will be set properly by savelev */ 150. #else 151. 	savelev(fd,dlevel); 152. #endif 153. 	saveobjchn(fd, invent); 154. 	savemonchn(fd, fallen_down); 155. 	savegenoinfo(fd); 156. 	tmp = getuid; 157. 	bwrite(fd, (genericptr_t) &tmp, sizeof tmp); 158. 	bwrite(fd, (genericptr_t) &flags, sizeof(struct flag)); 159. 	bwrite(fd, (genericptr_t) &dlevel, sizeof dlevel); 160. 	bwrite(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel); 161. 	bwrite(fd, (genericptr_t) &moves, sizeof moves); 162. 	bwrite(fd, (genericptr_t) &wiz_level, sizeof wiz_level); 163. 	bwrite(fd, (genericptr_t) &medusa_level, sizeof medusa_level); 164. #ifdef ORACLE 165. 	bwrite(fd, (genericptr_t) &oracle_level, sizeof oracle_level); 166. #endif 167. #ifdef REINCARNATION 168. 	bwrite(fd, (genericptr_t) &rogue_level, sizeof rogue_level); 169. #endif 170. #ifdef STRONGHOLD 171. 	bwrite(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level); 172. 	bwrite(fd, (genericptr_t) &tower_level, sizeof tower_level); 173. 	bwrite(fd, (genericptr_t) tune, sizeof tune); 174. #  ifdef MUSIC 175. 	bwrite(fd, (genericptr_t) &music_heard, sizeof music_heard); 176. #  endif 177. #endif 178. 	bwrite(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev); 179. 	bwrite(fd, (genericptr_t) &u, sizeof(struct you)); 180. #ifdef SPELLS 181. 	bwrite(fd, (genericptr_t) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 182. #endif 183. 	if(u.ustuck) 184. 		bwrite(fd, (genericptr_t) &(u.ustuck->m_id), sizeof u.ustuck->m_id); 185. 	bwrite(fd, (genericptr_t) pl_character, sizeof pl_character); 186. 	bwrite(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); 187. 	bwrite(fd, (genericptr_t) &current_fruit, sizeof current_fruit); 188. 	savefruitchn(fd); 189. 	savenames(fd); 190. #if defined(DGK) && !defined(TOS) 191. 	if (mode == COUNT) { 192. # ifdef ZEROCOMP 193. 		bflush(fd); 194. # endif 195. 		/* make sure there is enough disk space */ 196. 		needed = bytes_counted; 197. 		for (ltmp = 1; ltmp <= maxdlevel; ltmp++) 198. 			if (ltmp != dlevel && fileinfo[ltmp].where) 199. 				needed += fileinfo[ltmp].size + (sizeof ltmp); 200. 		fds = freediskspace(SAVEF); 201. 		if(needed > fds) { 202. 		    if(!hu) { 203. 			pline("There is insufficient space on SAVE disk."); 204. 			pline("Require %ld bytes but only have %ld.", needed,  205.  				fds); 206. 		    }  207.  		    flushout; 208. 		    (void) close(fd); 209. 		    (void) unlink(SAVEF); 210. 		    return 0; 211. 		}  212.  		mode = WRITE; 213. 		goto again; 214. 	}  215.  #endif 216. 	for(ltmp = (xchar)1; ltmp <= maxdlevel; ltmp++) { 217. #if defined(DGK) && !defined(TOS) 218. 		if (ltmp == dlevel || !fileinfo[ltmp].where) continue; 219. 		if (fileinfo[ltmp].where != ACTIVE) 220. 			swapin_file(ltmp); 221. #else 222. 		if(ltmp == dlevel || !level_exists[ltmp]) continue; 223. #endif 224. 		glo(ltmp); 225. #ifdef DGK 226. 		if(!hu) msmsg("."); 227. #endif 228. 		if((ofd = open(lock, OMASK)) < 0) { 229. 		    if(!hu) pline("Error while saving: cannot read %s.", lock); 230. 		    (void) close(fd); 231. 		    (void) unlink(SAVEF); 232. 		    if(!hu) done("tricked"); 233. 		    return(0); 234. 		}  235.  #ifdef ZEROCOMP 236. 		minit; 237. #endif 238. 		getlev(ofd, hackpid, ltmp, FALSE); 239. 		(void) close(ofd); 240. 		bwrite(fd, (genericptr_t) &ltmp, sizeof ltmp);  /* level number */ 241. #if defined(DGK) && !defined(TOS) 242. 		savelev(fd, ltmp, WRITE);			/* actual level */ 243. #else 244. 		savelev(fd, ltmp);			/* actual level */ 245. #endif 246. 		(void) unlink(lock); 247. 	}  248.  #ifdef ZEROCOMP 249. 	bflush(fd); 250. #endif 251. 	(void) close(fd); 252. 	glo(dlevel); 253. 	(void) unlink(lock);	/* get rid of current level --jgm */ 254. 	glo(0); 255. 	(void) unlink(lock); 256. #ifdef COMPRESS 257. 	Strcpy(cmd, COMPRESS); 258. 	Strcat(cmd, " "); 259. # ifdef COMPRESS_OPTIONS 260. 	Strcat(cmd, COMPRESS_OPTIONS); 261. 	Strcat(cmd, " "); 262. # endif 263. 	Strcat(cmd, SAVEF); 264. 	(void) system(cmd); 265. #endif 266. 	return(1); 267. }  268.   269.  #if defined(DGK) && !defined(TOS) 270. boolean 271. savelev(fd, lev, mode) 272. int fd; 273. xchar lev; 274. int mode; 275. {  276.  	if (mode & COUNT) { 277. # ifdef ZEROCOMP /* should be superfluous */ 278. 		if (!count_only)	/* did we just write? */ 279.  			bflush(0); 280. 		/*dbg;*/ 281. # endif 282. 		count_only = TRUE; 283. 		bytes_counted = 0; 284. 		savelev0(fd, lev); 285. 		while (bytes_counted > freediskspace(levels)) 286. 			if (!swapout_oldest) 287. 				return FALSE; 288. 	}  289.  	if (mode & WRITE) { 290. # ifdef ZEROCOMP 291. 		if (mode & COUNT)	/* did we just count? */ 292.  			bflush(fd); 293. # endif 294. 		count_only = FALSE; 295. 		bytes_counted = 0; 296. 		savelev0(fd, lev); 297. 	}  298.  	fileinfo[lev].where = ACTIVE; 299. 	fileinfo[lev].time = moves; 300. 	fileinfo[lev].size = bytes_counted; 301. 	return TRUE; 302. }  303.   304.  static 305. void 306. savelev0(fd,lev) 307. #else 308. void 309. savelev(fd,lev) 310. #endif 311. int fd; 312. xchar lev; 313. {  314.  #ifdef WORM 315. 	register struct wseg *wtmp; 316. 	register int tmp; 317. #endif 318. #ifdef TOS 319. 	short tlev; 320. #endif 321.  322.  	if(fd < 0) panic("Save on bad file!");	/* impossible */ 323. #if !defined(DGK) || defined(TOS) 324. 	if(lev >= 0 && lev <= MAXLEVEL) 325. 		level_exists[lev] = TRUE; 326. #endif 327. 	bwrite(fd,(genericptr_t) &hackpid,sizeof(hackpid)); 328. #ifdef TOS 329. 	tlev=lev; 330. 	bwrite(fd,(genericptr_t) &tlev,sizeof(tlev)); 331. #else 332. 	bwrite(fd,(genericptr_t) &lev,sizeof(lev)); 333. #endif 334. 	bwrite(fd,(genericptr_t) levl,sizeof(levl)); 335. #ifdef REINCARNATION 336. 	if(dlevel == rogue_level && lev != rogue_level) 337. 		/* save the symbols actually used to represent the level, not 338. 		 * those in use for the current level (the default symbols used  339.  		 * for rogue), since we will need to know whether to update 340. 		 * the display of the screen when the game is restored under 341. 		 * a potentially different value of showsyms from the 342. 		 * environment */ 343. 		/* if a game is saved off the rogue level, the usual showsyms 344. 		 * will be written out for the rogue level too, but they will 345. 		 * be ignored on restore so it doesn't matter */ 346. 		bwrite(fd, (genericptr_t) &savesyms, sizeof(struct symbols)); 347. 	else 348. #endif 349. 		bwrite(fd, (genericptr_t) &showsyms, sizeof(struct symbols)); 350. 	bwrite(fd,(genericptr_t) &moves,sizeof(long)); 351. 	bwrite(fd,(genericptr_t) &xupstair,sizeof(xupstair)); 352. 	bwrite(fd,(genericptr_t) &yupstair,sizeof(yupstair)); 353. 	bwrite(fd,(genericptr_t) &xdnstair,sizeof(xdnstair)); 354. 	bwrite(fd,(genericptr_t) &ydnstair,sizeof(ydnstair)); 355. #ifdef STRONGHOLD 356. 	bwrite(fd,(genericptr_t) &xupladder,sizeof(xupladder)); 357. 	bwrite(fd,(genericptr_t) &yupladder,sizeof(yupladder)); 358. 	bwrite(fd,(genericptr_t) &xdnladder,sizeof(xdnladder)); 359. 	bwrite(fd,(genericptr_t) &ydnladder,sizeof(ydnladder)); 360. #endif 361. 	bwrite(fd,(genericptr_t) &fountsound,sizeof(fountsound)); 362. 	bwrite(fd,(genericptr_t) &sinksound,sizeof(sinksound)); 363. 	savemonchn(fd, fmon); 364. 	savegoldchn(fd, fgold); 365. 	savetrapchn(fd, ftrap); 366.  367.  	saveobjchn(fd, fobj); 368. 	saveobjchn(fd, billobjs); 369.  370.  	save_engravings(fd); 371. 	bwrite(fd,(genericptr_t) rooms,sizeof(rooms)); 372. 	bwrite(fd,(genericptr_t) doors,sizeof(doors)); 373. #ifdef WORM 374. 	bwrite(fd,(genericptr_t) wsegs,sizeof(wsegs)); 375. 	for(tmp=1; tmp<32; tmp++){ 376. 		for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg){ 377. 			bwrite(fd,(genericptr_t) wtmp,sizeof(struct wseg)); 378. 		}  379.  #if defined(DGK) && !defined(TOS) 380. 		if (!count_only) 381. #endif 382. 			wsegs[tmp] = 0; 383. 	}  384.  	bwrite(fd,(genericptr_t) wgrowtime,sizeof(wgrowtime)); 385. #endif /* WORM /**/ 386. #if defined(DGK) && !defined(TOS) 387. 	if (count_only)	return; 388. #endif 389. 	billobjs = 0; 390. 	fgold = 0; 391. 	ftrap = 0; 392. 	fmon = 0; 393. 	fobj = 0; 394. }  395.   396.  #ifdef ZEROCOMP 397.  398.  #define RLESC '\0'    /* Leading character for run of LRESC's */ 399. #define flushoutrun(ln) bputc(RLESC); bputc(ln); ln = -1; 400.  401.  static unsigned char outbuf[BUFSZ]; 402. static unsigned short outbufp = 0; 403. static short outrunlength = -1; 404. static int bwritefd; 405.  406.  /*dbg 407. {  408.     if(!hu) printf("outbufp %d outrunlength %d\n", outbufp,outrunlength); 409. }*/  410.   411.  static void bputc(c) 412. unsigned char c;  413. { 414.  # ifdef DGK 415.     bytes_counted++; 416.     if (count_only) 417.       return; 418. # endif 419.     if (outbufp >= BUFSZ) { 420.       (void) write(bwritefd, outbuf, (int) BUFSZ); 421.       outbufp = 0; 422.     }  423.      outbuf[outbufp++] = c;  424. } 425.   426.  void 427. bflush(fd)  /* flush run and buffer */ 428. register int fd; 429. {  430.        bwritefd = fd; 431.       if (outrunlength >= 0) {    /* flush run */ 432. 	  flushoutrun(outrunlength); 433.       }  434.        if (outbufp) { 435. #ifdef	DGK 436. 	  if (!count_only)    /* flush buffer */ 437. #endif 438. 		  (void) write(fd, outbuf, outbufp); 439. 	  outbufp = 0; 440.       }  441.        /*printf("bflush"); getret;*/ 442. }  443.   444.  void 445. bwrite(fd, loc, num) 446. register int fd; 447. register genericptr_t loc; 448. register unsigned num; 449. {  450.        bwritefd = fd; 451.       for (num; num--, ((char *)loc)++) { 452. 	      if (*((char *)loc) == RLESC) { /* One more char in run */ 453. 		  if (++outrunlength == 0xFF) { 454. 		      flushoutrun(outrunlength); 455. 		  }  456.  	      } else { /* end of run */ 457. 		  if (outrunlength >= 0) {    /* flush run */ 458. 		      flushoutrun(outrunlength); 459. 		  }  460.  		  bputc(*((char *)loc)); 461. 	      }  462.        }  463.  }  464.   465.  #else /* ZEROCOMP */ 466.  467.  void 468. bwrite(fd,loc,num) 469. register int fd; 470. register genericptr_t loc; 471. register unsigned num; 472. {  473.  #if defined(DGK) && !defined(TOS) 474. 	bytes_counted += num; 475. 	if (!count_only) 476. #endif 477. /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ 478. #if defined(BSD) || defined(ULTRIX) 479. 	    if(write(fd, loc, (int)num) != (int)num) { 480. #else /* e.g. SYSV, __TURBOC__ */ 481. 	    if(write(fd, loc, num) != num) { 482. #endif 483. 		if(!hu) panic("cannot write %u bytes to file #%d", num, fd); 484. 		else	exit(1); 485. 	    }  486.  }  487.  #endif /* ZEROCOMP */ 488.  489.  static void 490. saveobjchn(fd,otmp) 491. register int fd; 492. register struct obj *otmp; 493. {  494.  	register struct obj *otmp2; 495. 	unsigned int xl; 496. 	int minusone = -1; 497.  498.  	while(otmp) { 499. 	    if(Is_container(otmp))	/* unlink contained objects */ 500. 		spill_objs(otmp);	/* (this rearranges the list) */ 501.  502.  	    otmp2 = otmp->nobj; 503. 	    xl = otmp->onamelth; 504. 	    bwrite(fd, (genericptr_t) &xl, sizeof(int)); 505. 	    bwrite(fd, (genericptr_t) otmp, xl + sizeof(struct obj)); 506. #if defined(DGK) && !defined(TOS) 507. 	    if (!count_only) 508. #endif 509. 		free((genericptr_t) otmp); 510. 	    otmp = otmp2; 511. 	}  512.  	bwrite(fd, (genericptr_t) &minusone, sizeof(int)); 513. }  514.   515.  static void 516. savemonchn(fd,mtmp) 517. register int fd; 518. register struct monst *mtmp; 519. {  520.  	register struct monst *mtmp2; 521. 	unsigned int xl; 522. 	int minusone = -1; 523. 	struct permonst *monbegin = &mons[0]; 524.  525.  	bwrite(fd, (genericptr_t) &monbegin, sizeof(monbegin)); 526.  527.  	while(mtmp) { 528. 		mtmp2 = mtmp->nmon; 529. 		xl = mtmp->mxlth + mtmp->mnamelth; 530. 		bwrite(fd, (genericptr_t) &xl, sizeof(int)); 531. 		bwrite(fd, (genericptr_t) mtmp, xl + sizeof(struct monst)); 532. 		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); 533. #if defined(DGK) && !defined(TOS) 534. 		if (!count_only) 535. #endif 536. 		free((genericptr_t) mtmp); 537. 		mtmp = mtmp2; 538. 	}  539.  	bwrite(fd, (genericptr_t) &minusone, sizeof(int)); 540. }  541.   542.  static void 543. savegoldchn(fd,gold) 544. register int fd; 545. register struct gold *gold; 546. {  547.  	register struct gold *gold2; 548. 	while(gold) { 549. 		gold2 = gold->ngold; 550. 		bwrite(fd, (genericptr_t) gold, sizeof(struct gold)); 551. #if defined(DGK) && !defined(TOS) 552. 		if (!count_only) 553. #endif 554. 			free((genericptr_t) gold); 555. 		gold = gold2; 556. 	}  557.  	bwrite(fd, (genericptr_t)nul, sizeof(struct gold)); 558. }  559.   560.  static void 561. savetrapchn(fd,trap) 562. register int fd; 563. register struct trap *trap; 564. {  565.  	register struct trap *trap2; 566. 	while(trap) { 567. 		trap2 = trap->ntrap; 568. 		bwrite(fd, (genericptr_t) trap, sizeof(struct trap)); 569. #if defined(DGK) && !defined(TOS) 570. 		if (!count_only) 571. #endif 572. 			free((genericptr_t) trap); 573. 		trap = trap2; 574. 	}  575.  	bwrite(fd, (genericptr_t)nul, sizeof(struct trap)); 576. }  577.   578.  /* save all the fruit names and ID's; this is used only in saving whole games 579.  * (not levels) and in saving bones levels. When saving a bones level, 580.  * we only want to save the fruits which exist on the bones level; the bones 581.  * level routine marks nonexistent fruits by making the fid negative. 582.  */  583.  void 584. savefruitchn(fd) 585. register int fd; 586. {  587.  	register struct fruit *f2; 588. 	while(ffruit) { 589. 		f2 = ffruit->nextf; 590. 		if (ffruit->fid >= 0) 591. 			bwrite(fd, (genericptr_t) ffruit, sizeof(struct fruit)); 592. 		free((genericptr_t) ffruit); 593. 		ffruit = f2; 594. 	}  595.  	bwrite(fd, (genericptr_t)nul, sizeof(struct fruit)); 596. }  597.   598.  static void 599. savegenoinfo(fd) 600. register int fd; 601. {  602.  	register int i;  603. 604. 	for (i = 0; i < NUMMONS; i++) 605. 		bwrite(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned)); 606. }  607.   608.  #if defined(DGK) && !defined(TOS) 609. boolean 610. swapin_file(lev) 611. int lev; 612. {  613.  	char to[PATHLEN], from[PATHLEN]; 614.  615.  	Sprintf(from, "%s%s", permbones, alllevels); 616. 	Sprintf(to, "%s%s", levels, alllevels); 617. 	name_file(from, lev); 618. 	name_file(to, lev); 619. 	while (fileinfo[lev].size > freediskspace(to)) 620. 		if (!swapout_oldest) 621. 			return FALSE; 622. #ifdef WIZARD 623. 	if (wizard) { 624. 		pline("Swapping in `%s'", from); 625. 		(void) fflush(stdout); 626. 	}  627.  #endif 628. 	copyfile(from, to); 629. 	(void) unlink(from); 630. 	fileinfo[lev].where = ACTIVE; 631. 	return TRUE; 632. }  633.   634.  static boolean 635. swapout_oldest { 636. 	char to[PATHLEN], from[PATHLEN]; 637. 	int i, oldest; 638. 	long oldtime; 639.  640.  	if (!ramdisk) 641. 		return FALSE; 642. 	for (i = 1, oldtime = 0, oldest = 0; i <= maxdlevel; i++) 643. 		if (fileinfo[i].where == ACTIVE  644.  		&& (!oldtime || fileinfo[i].time < oldtime)) { 645. 			oldest = i;  646. oldtime = fileinfo[i].time; 647. 		}  648.  	if (!oldest) 649. 		return FALSE; 650. 	Sprintf(from, "%s%s", levels, alllevels); 651. 	Sprintf(to, "%s%s", permbones, alllevels); 652. 	name_file(from, oldest); 653. 	name_file(to, oldest); 654. #ifdef WIZARD 655. 	if (wizard) { 656. 		pline("Swapping out `%s'.", from); 657. 		(void) fflush(stdout); 658. 	}  659.  #endif 660. 	copyfile(from, to); 661. 	(void) unlink(from); 662. 	fileinfo[oldest].where = SWAPPED; 663. 	return TRUE; 664. }  665.   666.  static 667. void 668. copyfile(from, to) 669. char *from, *to; 670. {  671.  	char buf[BUFSIZ]; 672. 	int nfrom, nto, fdfrom, fdto; 673.  674.  	if ((fdfrom = open(from, O_RDONLY | O_BINARY, FCMASK)) < 0) 675. 		panic("Can't copy from %s !?", from); 676. 	if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK)) < 0) 677. 		panic("Can't copy to %s", to); 678. 	do { 679. 		nfrom = read(fdfrom, buf, BUFSIZ); 680. 		nto = write(fdto, buf, nfrom); 681. 		if (nto != nfrom) 682. 			panic("Copyfile failed!"); 683. 	} while (nfrom == BUFSIZ); 684. 	(void) close(fdfrom); 685. 	(void) close(fdto); 686. }  687.  #endif 688.  689.  /*  690.   * "spill" objects out of containers (unlinking from the fcobj list). 691.  *  692.   * The objects will be rearranged, and properly aged. When we restore, they 693.  * can be put back into their containers. By the time all of the calls to 694. * saveobjchn been made, the fcobj list should be empty. Thus it need not 695.  * be saved, and doing so could cause some strange addressing problems. 696.  *  697.   * NOTE:  The cobj field is set to -1. It will be used as a flag to indicate 698.  *	  that this object was previously in a container. 699.  */  700.   701.  static void 702. spill_objs(cobj) 703. register struct obj *cobj; 704. {  705.  	register struct obj *otmp, *otmp2, *probj; 706.  707.  #ifdef LINT 708. 	probj = (struct obj *)0;    /* suppress "used before set" error */ 709. #endif 710. 	for(otmp = fcobj; otmp; otmp = otmp2) { 711.  712.  	    otmp2 = otmp->nobj; 713. 	    if(otmp->cobj == cobj) { 714.  715.  		if(cobj->cursed && rn2(2))	otmp->cursed = 1; 716. 	/*  717.  	 * Place all of the objects in a given container after that container 718. 	 * in the list. On restore, they should be able to be picked up and 719. 	 * put back in. 720. 	 */  721.  		if(otmp == fcobj) fcobj = otmp2; 722. 		else		  probj->nobj = otmp2; 723.  724.  		otmp->nobj = cobj->nobj; 725. 		cobj->nobj = otmp; 726. 		otmp->cobj = (struct obj *)-1; 727. 	    } else probj = otmp; 728. 	}  729.   730.  }