Source:NetHack 2.3e/save.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to save.c from the source code of NetHack 2.3e.

Warning! This is the source code from an old release. For newer releases, see Source code

Screenshots and source code from Hack are used under the CWI license.

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