xref: /netbsd/games/hack/hack.save.c (revision bf9ec67e)
1 /*	$NetBSD: hack.save.c,v 1.7 2001/03/25 20:44:02 jsm Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: hack.save.c,v 1.7 2001/03/25 20:44:02 jsm Exp $");
10 #endif				/* not lint */
11 
12 #include <signal.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include "hack.h"
17 #include "extern.h"
18 
19 
20 int
21 dosave()
22 {
23 	if (dosave0(0)) {
24 		settty("Be seeing you ...\n");
25 		exit(0);
26 	}
27 	return (0);
28 }
29 
30 #ifndef NOSAVEONHANGUP
31 void
32 hangup(n)
33 	int n __attribute__((__unused__));
34 {
35 	(void) dosave0(1);
36 	exit(1);
37 }
38 #endif	/* NOSAVEONHANGUP */
39 
40 /* returns 1 if save successful */
41 int
42 dosave0(hu)
43 	int             hu;
44 {
45 	int		fd, ofd;
46 	int             tmp;	/* not ! */
47 
48 	(void) signal(SIGHUP, SIG_IGN);
49 	(void) signal(SIGINT, SIG_IGN);
50 	if ((fd = creat(SAVEF, FMASK)) < 0) {
51 		if (!hu)
52 			pline("Cannot open save file. (Continue or Quit)");
53 		(void) unlink(SAVEF);	/* ab@unido */
54 		return (0);
55 	}
56 	if (flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
57 		u.uluck--;	/* and unido!ab */
58 	savelev(fd, dlevel);
59 	saveobjchn(fd, invent);
60 	saveobjchn(fd, fcobj);
61 	savemonchn(fd, fallen_down);
62 	tmp = getuid();
63 	bwrite(fd, (char *) &tmp, sizeof tmp);
64 	bwrite(fd, (char *) &flags, sizeof(struct flag));
65 	bwrite(fd, (char *) &dlevel, sizeof dlevel);
66 	bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
67 	bwrite(fd, (char *) &moves, sizeof moves);
68 	bwrite(fd, (char *) &u, sizeof(struct you));
69 	if (u.ustuck)
70 		bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
71 	bwrite(fd, (char *) pl_character, sizeof pl_character);
72 	bwrite(fd, (char *) genocided, sizeof genocided);
73 	bwrite(fd, (char *) fut_geno, sizeof fut_geno);
74 	savenames(fd);
75 	for (tmp = 1; tmp <= maxdlevel; tmp++) {
76 
77 		if (tmp == dlevel || !level_exists[tmp])
78 			continue;
79 		glo(tmp);
80 		if ((ofd = open(lock, O_RDONLY)) < 0) {
81 			if (!hu)
82 				pline("Error while saving: cannot read %s.", lock);
83 			(void) close(fd);
84 			(void) unlink(SAVEF);
85 			if (!hu)
86 				done("tricked");
87 			return (0);
88 		}
89 		getlev(ofd, hackpid, tmp);
90 		(void) close(ofd);
91 		bwrite(fd, (char *) &tmp, sizeof tmp);	/* level number */
92 		savelev(fd, tmp);	/* actual level */
93 		(void) unlink(lock);
94 	}
95 	(void) close(fd);
96 	glo(dlevel);
97 	(void) unlink(lock);	/* get rid of current level --jgm */
98 	glo(0);
99 	(void) unlink(lock);
100 	return (1);
101 }
102 
103 int
104 dorecover(fd)
105 	int fd;
106 {
107 	int nfd;
108 	int             tmp;	/* not a ! */
109 	unsigned        mid;	/* idem */
110 	struct obj     *otmp;
111 
112 	restoring = TRUE;
113 	getlev(fd, 0, 0);
114 	invent = restobjchn(fd);
115 	for (otmp = invent; otmp; otmp = otmp->nobj)
116 		if (otmp->owornmask)
117 			setworn(otmp, otmp->owornmask);
118 	fcobj = restobjchn(fd);
119 	fallen_down = restmonchn(fd);
120 	mread(fd, (char *) &tmp, sizeof tmp);
121 	if (tmp != getuid()) {	/* strange ... */
122 		(void) close(fd);
123 		(void) unlink(SAVEF);
124 		puts("Saved game was not yours.");
125 		restoring = FALSE;
126 		return (0);
127 	}
128 	mread(fd, (char *) &flags, sizeof(struct flag));
129 	mread(fd, (char *) &dlevel, sizeof dlevel);
130 	mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
131 	mread(fd, (char *) &moves, sizeof moves);
132 	mread(fd, (char *) &u, sizeof(struct you));
133 	if (u.ustuck)
134 		mread(fd, (char *) &mid, sizeof mid);
135 	mread(fd, (char *) pl_character, sizeof pl_character);
136 	mread(fd, (char *) genocided, sizeof genocided);
137 	mread(fd, (char *) fut_geno, sizeof fut_geno);
138 	restnames(fd);
139 	while (1) {
140 		if (read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
141 			break;
142 		getlev(fd, 0, tmp);
143 		glo(tmp);
144 		if ((nfd = creat(lock, FMASK)) < 0)
145 			panic("Cannot open temp file %s!\n", lock);
146 		savelev(nfd, tmp);
147 		(void) close(nfd);
148 	}
149 	(void) lseek(fd, (off_t) 0, SEEK_SET);
150 	getlev(fd, 0, 0);
151 	(void) close(fd);
152 	(void) unlink(SAVEF);
153 	if (Punished) {
154 		for (otmp = fobj; otmp; otmp = otmp->nobj)
155 			if (otmp->olet == CHAIN_SYM)
156 				goto chainfnd;
157 		panic("Cannot find the iron chain?");
158 chainfnd:
159 		uchain = otmp;
160 		if (!uball) {
161 			for (otmp = fobj; otmp; otmp = otmp->nobj)
162 				if (otmp->olet == BALL_SYM && otmp->spe)
163 					goto ballfnd;
164 			panic("Cannot find the iron ball?");
165 	ballfnd:
166 			uball = otmp;
167 		}
168 	}
169 	if (u.ustuck) {
170 		struct monst   *mtmp;
171 
172 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
173 			if (mtmp->m_id == mid)
174 				goto monfnd;
175 		panic("Cannot find the monster ustuck.");
176 monfnd:
177 		u.ustuck = mtmp;
178 	}
179 #ifndef QUEST
180 	setsee();		/* only to recompute seelx etc. - these
181 				 * weren't saved */
182 #endif	/* QUEST */
183 	docrt();
184 	restoring = FALSE;
185 	return (1);
186 }
187 
188 struct obj     *
189 restobjchn(fd)
190 	int fd;
191 {
192 	struct obj     *otmp, *otmp2 = NULL;
193 	struct obj     *first = 0;
194 	int             xl;
195 	while (1) {
196 		mread(fd, (char *) &xl, sizeof(xl));
197 		if (xl == -1)
198 			break;
199 		otmp = newobj(xl);
200 		if (!first)
201 			first = otmp;
202 		else
203 			otmp2->nobj = otmp;
204 		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
205 		if (!otmp->o_id)
206 			otmp->o_id = flags.ident++;
207 		otmp2 = otmp;
208 	}
209 	if (first && otmp2->nobj) {
210 		impossible("Restobjchn: error reading objchn.");
211 		otmp2->nobj = 0;
212 	}
213 	return (first);
214 }
215 
216 struct monst   *
217 restmonchn(fd)
218 	int fd;
219 {
220 	struct monst   *mtmp, *mtmp2 = NULL;
221 	struct monst   *first = 0;
222 	int             xl;
223 
224 	struct permonst *monbegin;
225 	long            differ;
226 
227 	mread(fd, (char *) &monbegin, sizeof(monbegin));
228 	differ = (const char *) (&mons[0]) - (const char *) (monbegin);
229 
230 #ifdef lint
231 	/* suppress "used before set" warning from lint */
232 	mtmp2 = 0;
233 #endif	/* lint */
234 	while (1) {
235 		mread(fd, (char *) &xl, sizeof(xl));
236 		if (xl == -1)
237 			break;
238 		mtmp = newmonst(xl);
239 		if (!first)
240 			first = mtmp;
241 		else
242 			mtmp2->nmon = mtmp;
243 		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
244 		if (!mtmp->m_id)
245 			mtmp->m_id = flags.ident++;
246 		mtmp->data = (const struct permonst *)
247 			((const char *) mtmp->data + differ);
248 		if (mtmp->minvent)
249 			mtmp->minvent = restobjchn(fd);
250 		mtmp2 = mtmp;
251 	}
252 	if (first && mtmp2->nmon) {
253 		impossible("Restmonchn: error reading monchn.");
254 		mtmp2->nmon = 0;
255 	}
256 	return (first);
257 }
258