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