Source:NetHack 3.0.0/save.c

From NetHackWiki
Revision as of 05:26, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/save.c moved to Source:NetHack 3.0.0/save.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

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.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 <signal.h>
16.   #endif /* !TOS */
17.   #ifdef EXPLORE_MODE
18.   #include <fcntl.h>
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.  }