Source:NetHack 1.3d/save.c

From NetHackWiki
Jump to: navigation, search

Below is the full text to save.c from the source code of NetHack 1.3d. To link to a particular line, write [[NetHack 1.3d/save.c#line123]], for example.

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

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

1.    /*	SCCS Id: @(#)save.c	1.3	87/07/14
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* save.c - version 1.0.3 */
4.    
5.    #include <signal.h>
6.    #include <stdio.h>
7.    #include "hack.h"
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.   	(void) signal(SIGINT, SIG_IGN);
50.   #ifdef DGK
51.   	if (!saveDiskPrompt(0))
52.   		return 0;
53.   	fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK);
54.   #else
55.   	fd = creat(SAVEF, FMASK);
56.   #endif
57.   	if(fd < 0) {
58.   		if(!hu) pline("Cannot open save file. (Continue or Quit)");
59.   		(void) unlink(SAVEF);		/* ab@unido */
60.   		return(0);
61.   	}
62.   	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
63.   		u.uluck--;			/* and unido!ab */
64.   #ifdef DGKMOD
65.   	home();
66.   	cl_end();
67.   #endif
68.   #ifdef DGK
69.   	msmsg("Saving: ");
70.   	mode = COUNT;
71.   again:
72.   	savelev(fd, dlevel, mode);
73.   	/* count_only will be set properly by savelev */
74.   #else
75.   	savelev(fd,dlevel);
76.   #endif
77.   	saveobjchn(fd, invent);
78.   	saveobjchn(fd, fcobj);
79.   	savemonchn(fd, fallen_down);
80.   	tmp = getuid();
81.   	bwrite(fd, (char *) &tmp, sizeof tmp);
82.   	bwrite(fd, (char *) &flags, sizeof(struct flag));
83.   	bwrite(fd, (char *) &dlevel, sizeof dlevel);
84.   	bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
85.   	bwrite(fd, (char *) &moves, sizeof moves);
86.   	bwrite(fd, (char *) &u, sizeof(struct you));
87.   #ifdef SPELLS
88.   	bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
89.   #endif
90.   	if(u.ustuck)
91.   		bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
92.   	bwrite(fd, (char *) pl_character, sizeof pl_character);
93.   	bwrite(fd, (char *) genocided, sizeof genocided);
94.   	bwrite(fd, (char *) fut_geno, sizeof fut_geno);
95.   #ifdef HARD
96.   	bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst));
97.   #endif
98.   	savenames(fd);
99.   #ifdef DGK
100.  	if (mode == COUNT) {
101.  		/* make sure there is enough disk space */
102.  		needed = bytes_counted;
103.  		for (tmp = 1; tmp <= maxdlevel; tmp++)
104.  			if (tmp != dlevel && fileinfo[tmp].where)
105.  				needed += fileinfo[tmp].size + (sizeof tmp);
106.  		fds = freediskspace(SAVEF);
107.  		if (needed > fds) {
108.  			pline("There is insufficient space on SAVE disk.");
109.  			pline("Require %ld bytes but only have %ld.", needed,
110.  				fds);
111.  			flushout();
112.  			(void) close(fd);
113.  			(void) unlink(SAVEF);
114.  			return 0;
115.  		}
116.  		mode = WRITE;
117.  		goto again;
118.  	}
119.  #endif
120.  	for(tmp = 1; tmp <= maxdlevel; tmp++) {
121.  		extern int hackpid;
122.  #ifdef DGK
123.  		if (tmp == dlevel || !fileinfo[tmp].where) continue;
124.  		if (fileinfo[tmp].where != ACTIVE)
125.  			swapin_file(tmp);
126.  #else
127.  		extern boolean level_exists[];
128.  
129.  		if(tmp == dlevel || !level_exists[tmp]) continue;
130.  #endif
131.  		glo(tmp);
132.  #ifdef DGK
133.  		msmsg(".");
134.  #endif
135.  		if((ofd = open(lock, 0)) < 0) {
136.  		    if(!hu) pline("Error while saving: cannot read %s.", lock);
137.  		    (void) close(fd);
138.  		    (void) unlink(SAVEF);
139.  		    if(!hu) done("tricked");
140.  		    return(0);
141.  		}
142.  		getlev(ofd, hackpid, tmp);
143.  		(void) close(ofd);
144.  		bwrite(fd, (char *) &tmp, sizeof tmp);	/* level number */
145.  #ifdef DGK
146.  		savelev(fd,tmp,WRITE);			/* actual level */
147.  #else
148.  		savelev(fd,tmp);			/* actual level */
149.  #endif
150.  		(void) unlink(lock);
151.  	}
152.  	(void) close(fd);
153.  	glo(dlevel);
154.  	(void) unlink(lock);	/* get rid of current level --jgm */
155.  	glo(0);
156.  	(void) unlink(lock);
157.  	return(1);
158.  }
159.  
160.  dorecover(fd)
161.  register fd;
162.  {
163.  	register nfd;
164.  	int tmp;		/* not a register ! */
165.  	unsigned mid;		/* idem */
166.  	struct obj *otmp;
167.  	extern boolean restoring;
168.  #ifdef DGK
169.  	struct flag oldflags;
170.  
171.  	oldflags = flags;	/* Save flags set in the config file */
172.  #endif
173.  	restoring = TRUE;
174.  	getlev(fd, 0, 0);
175.  	invent = restobjchn(fd);
176.  	for(otmp = invent; otmp; otmp = otmp->nobj)
177.  		if(otmp->owornmask)
178.  			setworn(otmp, otmp->owornmask);
179.  	fcobj = restobjchn(fd);
180.  	fallen_down = restmonchn(fd);
181.  	mread(fd, (char *) &tmp, sizeof tmp);
182.  	if(tmp != getuid()) {		/* strange ... */
183.  		(void) close(fd);
184.  		(void) unlink(SAVEF);
185.  		puts("Saved game was not yours.");
186.  		restoring = FALSE;
187.  		return(0);
188.  	}
189.  	mread(fd, (char *) &flags, sizeof(struct flag));
190.  #ifdef DGK
191.  	/* Some config file OPTIONS take precedence over those in save file.
192.  	 */
193.  	flags.rawio = oldflags.rawio;
194.  	flags.DECRainbow = oldflags.DECRainbow;
195.  	flags.IBMBIOS = oldflags.IBMBIOS;
196.  #endif
197.  	mread(fd, (char *) &dlevel, sizeof dlevel);
198.  	mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
199.  	mread(fd, (char *) &moves, sizeof moves);
200.  	mread(fd, (char *) &u, sizeof(struct you));
201.  #ifdef SPELLS
202.  	mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
203.  #endif
204.  	if(u.ustuck)
205.  		mread(fd, (char *) &mid, sizeof mid);
206.  	mread(fd, (char *) pl_character, sizeof pl_character);
207.  	mread(fd, (char *) genocided, sizeof genocided);
208.  	mread(fd, (char *) fut_geno, sizeof fut_geno);
209.  #ifdef HARD
210.  	mread(fd, (char *) &pm_wizard, sizeof(struct permonst));
211.  #endif
212.  	restnames(fd);
213.  #ifdef DGK
214.  	msmsg("\n");
215.  	cl_end();
216.  	msmsg("You got as far as level %d%s.\n", maxdlevel,
217.  		flags.debug ? " in WIZARD mode" : "");
218.  	cl_end();
219.  	msmsg("Restoring: ");
220.  #endif
221.  	while(1) {
222.  		if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
223.  			break;
224.  		getlev(fd, 0, tmp);
225.  		glo(tmp);
226.  #ifdef DGK
227.  		msmsg(".");
228.  		nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK);
229.  #else
230.  		nfd = creat(lock, FMASK);
231.  #endif
232.  		if (nfd < 0)	panic("Cannot open temp file %s!\n", lock);
233.  #ifdef DGK
234.  		if (!savelev(nfd, tmp, COUNT | WRITE)) {
235.  
236.  			/* The savelev can't proceed because the size required
237.  			 * is greater than the available disk space.
238.  			 */
239.  			msmsg("\nNot enough space on `%s' to restore your game.\n",
240.  				levels);
241.  
242.  			/* Remove levels and bones that may have been created.
243.  			 */
244.  			(void) close(nfd);
245.  			eraseall(levels, alllevels);
246.  			eraseall(levels, allbones);
247.  
248.  			/* Perhaps the person would like to play without a
249.  			 * RAMdisk.
250.  			 */
251.  			if (ramdisk) {
252.  				/* PlaywoRAMdisk may not return, but if it does
253.  				 * it is certain that ramdisk will be 0.
254.  				 */
255.  				playwoRAMdisk();
256.  				(void) lseek(fd, 0L, 0); /* Rewind save file */
257.  				return dorecover(fd);	 /* and try again */
258.  			} else {
259.  				msmsg("Be seeing you ...\n");
260.  				exit(0);
261.  			}
262.  		}
263.  #else
264.  		savelev(nfd,tmp);
265.  #endif
266.  		(void) close(nfd);
267.  	}
268.  	(void) lseek(fd, 0L, 0);
269.  	getlev(fd, 0, 0);
270.  	(void) close(fd);
271.  	(void) unlink(SAVEF);
272.  	if(Punished) {
273.  		for(otmp = fobj; otmp; otmp = otmp->nobj)
274.  			if(otmp->olet == CHAIN_SYM) goto chainfnd;
275.  		panic("Cannot find the iron chain?");
276.  	chainfnd:
277.  		uchain = otmp;
278.  		if(!uball){
279.  			for(otmp = fobj; otmp; otmp = otmp->nobj)
280.  				if(otmp->olet == BALL_SYM && otmp->spe)
281.  					goto ballfnd;
282.  			panic("Cannot find the iron ball?");
283.  		ballfnd:
284.  			uball = otmp;
285.  		}
286.  	}
287.  	if(u.ustuck) {
288.  		register struct monst *mtmp;
289.  
290.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
291.  			if(mtmp->m_id == mid) goto monfnd;
292.  		panic("Cannot find the monster ustuck.");
293.  	monfnd:
294.  		u.ustuck = mtmp;
295.  	}
296.  #ifndef QUEST
297.  	setsee();  /* only to recompute seelx etc. - these weren't saved */
298.  #endif
299.  #ifdef DGK
300.  	gameDiskPrompt();
301.  #endif
302.  	docrt();
303.  	restoring = FALSE;
304.  	return(1);
305.  }
306.  
307.  struct obj *
308.  restobjchn(fd)
309.  register fd;
310.  {
311.  	register struct obj *otmp, *otmp2;
312.  	register struct obj *first = 0;
313.  	int xl;
314.  #ifdef lint
315.  	/* suppress "used before set" warning from lint */
316.  	otmp2 = 0;
317.  #endif
318.  	while(1) {
319.  		mread(fd, (char *) &xl, sizeof(xl));
320.  		if(xl == -1) break;
321.  		otmp = newobj(xl);
322.  		if(!first) first = otmp;
323.  		else otmp2->nobj = otmp;
324.  		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
325.  		if(!otmp->o_id) otmp->o_id = flags.ident++;
326.  		otmp2 = otmp;
327.  	}
328.  	if(first && otmp2->nobj){
329.  		impossible("Restobjchn: error reading objchn.");
330.  		otmp2->nobj = 0;
331.  	}
332.  	return(first);
333.  }
334.  #ifdef MSDOS
335.  struct monst *
336.  restmonchn(fd)
337.  register fd;
338.  {
339.  	register struct monst *mtmp, *mtmp2;
340.  	register struct monst *first = 0;
341.  	int xl;
342.  	int monsindex;
343.  	extern struct permonst li_dog, dog, la_dog;
344.  #ifdef KAA
345.  	extern struct permonst hell_hound;
346.  # ifdef HARD
347.  	extern struct permonst d_lord, d_prince;
348.  # endif
349.  #endif
350.  
351.  #ifdef lint
352.  	/* suppress "used before set" warning from lint */
353.  	mtmp2 = 0;
354.  #endif /* lint /**/
355.  	while(1) {
356.  		mread(fd, (char *) &xl, sizeof(xl));
357.  		if(xl == -1) break;
358.  		mtmp = newmonst(xl);
359.  		if(!first) first = mtmp;
360.  		else mtmp2->nmon = mtmp;
361.  		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
362.  		if(!mtmp->m_id)
363.  			mtmp->m_id = flags.ident++;
364.  		monsindex = *((int *)&mtmp->data);
365.  		if (monsindex == -1)		/* Special fake index */
366.  			mtmp->data = &li_dog;
367.  		else if (monsindex == -2)	/* Special fake index */
368.  			mtmp->data = &dog;
369.  		else if (monsindex == -3)	/* Special fake index */
370.  			mtmp->data = &la_dog;
371.  #ifdef KAA
372.  		else if (monsindex == -4)
373.  			mtmp->data = &hell_hound;
374.  # ifdef HARD
375.  		else if (monsindex == -5)
376.  			permonstp = &d_lord;
377.  
378.  		else if (monsindex == -6)
379.  			permonstp = &d_prince;
380.  # endif
381.  #endif
382.  		else
383.  			mtmp->data = &mons[monsindex];
384.  		if(mtmp->minvent)
385.  			mtmp->minvent = restobjchn(fd);
386.  		mtmp2 = mtmp;
387.  	}
388.  	if(first && mtmp2->nmon){
389.  		impossible("Restmonchn: error reading monchn.");
390.  		mtmp2->nmon = 0;
391.  	}
392.  	return(first);
393.  }
394.  #else
395.  struct monst *
396.  restmonchn(fd)
397.  register fd;
398.  {
399.  	register struct monst *mtmp, *mtmp2;
400.  	register struct monst *first = 0;
401.  	int xl;
402.  
403.  	struct permonst *monbegin;
404.  	long differ;
405.  
406.  	mread(fd, (char *)&monbegin, sizeof(monbegin));
407.  	differ = (char *)(&mons[0]) - (char *)(monbegin);
408.  
409.  #ifdef lint
410.  	/* suppress "used before set" warning from lint */
411.  	mtmp2 = 0;
412.  #endif
413.  	while(1) {
414.  		mread(fd, (char *) &xl, sizeof(xl));
415.  		if(xl == -1) break;
416.  		mtmp = newmonst(xl);
417.  		if(!first) first = mtmp;
418.  		else mtmp2->nmon = mtmp;
419.  		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
420.  		if(!mtmp->m_id)
421.  			mtmp->m_id = flags.ident++;
422.  		mtmp->data = (struct permonst *)
423.  			((char *) mtmp->data + differ);
424.  		if(mtmp->minvent)
425.  			mtmp->minvent = restobjchn(fd);
426.  		mtmp2 = mtmp;
427.  	}
428.  	if(first && mtmp2->nmon){
429.  		impossible("Restmonchn: error reading monchn.");
430.  		mtmp2->nmon = 0;
431.  	}
432.  	return(first);
433.  }
434.  #endif