Fandom

Wikihack

Source:NetHack 1.4f/save.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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

Also on Fandom

Random Wiki