xref: /dragonfly/games/hack/hack.save.c (revision e6d22e9b)
1 /*	$NetBSD: hack.save.c,v 1.16 2011/08/06 20:42:43 dholland Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <signal.h>
65 #include <stdlib.h>
66 #include <unistd.h>
67 #include <fcntl.h>
68 #include "hack.h"
69 #include "extern.h"
70 
71 static int dosave0(int);
72 
73 int
74 dosave(void)
75 {
76 	if (dosave0(0)) {
77 		settty("Be seeing you ...\n");
78 		exit(0);
79 	}
80 	return (0);
81 }
82 
83 #ifndef NOSAVEONHANGUP
84 void
85 hang_up(int n __unused)
86 {
87 	(void) dosave0(1);
88 	exit(1);
89 }
90 #endif	/* NOSAVEONHANGUP */
91 
92 /* returns 1 if save successful */
93 static int
94 dosave0(int hu)
95 {
96 	int		fd, ofd;
97 	int             tmp;	/* not ! */
98 
99 	(void) signal(SIGHUP, SIG_IGN);
100 	(void) signal(SIGINT, SIG_IGN);
101 	if ((fd = creat(SAVEF, FMASK)) < 0) {
102 		if (!hu)
103 			pline("Cannot open save file. (Continue or Quit)");
104 		(void) unlink(SAVEF);	/* ab@unido */
105 		return (0);
106 	}
107 	if (flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
108 		u.uluck--;	/* and unido!ab */
109 	savelev(fd, dlevel);
110 	saveobjchn(fd, invent);
111 	saveobjchn(fd, fcobj);
112 	savemonchn(fd, fallen_down);
113 	tmp = getuid();
114 	bwrite(fd, &tmp, sizeof tmp);
115 	bwrite(fd, &flags, sizeof(struct flag));
116 	bwrite(fd, &dlevel, sizeof dlevel);
117 	bwrite(fd, &maxdlevel, sizeof maxdlevel);
118 	bwrite(fd, &moves, sizeof moves);
119 	bwrite(fd, &u, sizeof(struct you));
120 	if (u.ustuck)
121 		bwrite(fd, &(u.ustuck->m_id), sizeof u.ustuck->m_id);
122 	bwrite(fd, pl_character, sizeof pl_character);
123 	bwrite(fd, genocided, sizeof genocided);
124 	bwrite(fd, fut_geno, sizeof fut_geno);
125 	savenames(fd);
126 	for (tmp = 1; tmp <= maxdlevel; tmp++) {
127 
128 		if (tmp == dlevel || !level_exists[tmp])
129 			continue;
130 		glo(tmp);
131 		if ((ofd = open(lock, O_RDONLY)) < 0) {
132 			if (!hu)
133 				pline("Error while saving: cannot read %s.", lock);
134 			(void) close(fd);
135 			(void) unlink(SAVEF);
136 			if (!hu)
137 				done("tricked");
138 			return (0);
139 		}
140 		getlev(ofd, hackpid, tmp);
141 		(void) close(ofd);
142 		bwrite(fd, &tmp, sizeof tmp);	/* level number */
143 		savelev(fd, tmp);	/* actual level */
144 		(void) unlink(lock);
145 	}
146 	(void) close(fd);
147 	glo(dlevel);
148 	(void) unlink(lock);	/* get rid of current level --jgm */
149 	glo(0);
150 	(void) unlink(lock);
151 	return (1);
152 }
153 
154 int
155 dorecover(int fd)
156 {
157 	int nfd;
158 	int             tmp;	/* not a ! */
159 	unsigned        mid;	/* idem */
160 	struct obj     *otmp;
161 
162 	restoring = TRUE;
163 	getlev(fd, 0, 0);
164 	invent = restobjchn(fd);
165 	for (otmp = invent; otmp; otmp = otmp->nobj)
166 		if (otmp->owornmask)
167 			setworn(otmp, otmp->owornmask);
168 	fcobj = restobjchn(fd);
169 	fallen_down = restmonchn(fd);
170 	mread(fd, &tmp, sizeof tmp);
171 	if (tmp != (int) getuid()) {	/* strange ... */
172 		(void) close(fd);
173 		(void) unlink(SAVEF);
174 		puts("Saved game was not yours.");
175 		restoring = FALSE;
176 		return (0);
177 	}
178 	mread(fd, &flags, sizeof(struct flag));
179 	mread(fd, &dlevel, sizeof dlevel);
180 	mread(fd, &maxdlevel, sizeof maxdlevel);
181 	mread(fd, &moves, sizeof moves);
182 	mread(fd, &u, sizeof(struct you));
183 	if (u.ustuck)
184 		mread(fd, &mid, sizeof mid);
185 	mread(fd, pl_character, sizeof pl_character);
186 	mread(fd, genocided, sizeof genocided);
187 	mread(fd, fut_geno, sizeof fut_geno);
188 	restnames(fd);
189 	while (1) {
190 		if (read(fd, &tmp, sizeof tmp) != sizeof tmp)
191 			break;
192 		getlev(fd, 0, tmp);
193 		glo(tmp);
194 		if ((nfd = creat(lock, FMASK)) < 0)
195 			panic("Cannot open temp file %s!\n", lock);
196 		savelev(nfd, tmp);
197 		(void) close(nfd);
198 	}
199 	(void) lseek(fd, (off_t) 0, SEEK_SET);
200 	getlev(fd, 0, 0);
201 	(void) close(fd);
202 	(void) unlink(SAVEF);
203 	if (Punished) {
204 		for (otmp = fobj; otmp; otmp = otmp->nobj)
205 			if (otmp->olet == CHAIN_SYM)
206 				goto chainfnd;
207 		panic("Cannot find the iron chain?");
208 chainfnd:
209 		uchain = otmp;
210 		if (!uball) {
211 			for (otmp = fobj; otmp; otmp = otmp->nobj)
212 				if (otmp->olet == BALL_SYM && otmp->spe)
213 					goto ballfnd;
214 			panic("Cannot find the iron ball?");
215 	ballfnd:
216 			uball = otmp;
217 		}
218 	}
219 	if (u.ustuck) {
220 		struct monst   *mtmp;
221 
222 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
223 			if (mtmp->m_id == mid)
224 				goto monfnd;
225 		panic("Cannot find the monster ustuck.");
226 monfnd:
227 		u.ustuck = mtmp;
228 	}
229 #ifndef QUEST
230 	setsee();		/* only to recompute seelx etc. - these
231 				 * weren't saved */
232 #endif	/* QUEST */
233 	docrt();
234 	restoring = FALSE;
235 	return (1);
236 }
237 
238 struct obj     *
239 restobjchn(int fd)
240 {
241 	struct obj     *otmp, *otmp2 = NULL;
242 	struct obj     *first = 0;
243 	int             xl;
244 	while (1) {
245 		mread(fd, &xl, sizeof(xl));
246 		if (xl == -1)
247 			break;
248 		otmp = newobj(xl);
249 		if (!first)
250 			first = otmp;
251 		else
252 			otmp2->nobj = otmp;
253 		mread(fd, otmp, (unsigned) xl + sizeof(struct obj));
254 		if (!otmp->o_id)
255 			otmp->o_id = flags.ident++;
256 		otmp2 = otmp;
257 	}
258 	if (first && otmp2->nobj) {
259 		impossible("Restobjchn: error reading objchn.");
260 		otmp2->nobj = 0;
261 	}
262 	return (first);
263 }
264 
265 struct monst   *
266 restmonchn(int fd)
267 {
268 	struct monst   *mtmp, *mtmp2 = NULL;
269 	struct monst   *first = 0;
270 	int             xl;
271 
272 	struct permonst *monbegin;
273 	long            differ;
274 
275 	mread(fd, &monbegin, sizeof(monbegin));
276 	differ = (const char *) (&mons[0]) - (const char *) (monbegin);
277 
278 #ifdef lint
279 	/* suppress "used before set" warning from lint */
280 	mtmp2 = 0;
281 #endif	/* lint */
282 	while (1) {
283 		mread(fd, &xl, sizeof(xl));
284 		if (xl == -1)
285 			break;
286 		mtmp = newmonst(xl);
287 		if (!first)
288 			first = mtmp;
289 		else
290 			mtmp2->nmon = mtmp;
291 		mread(fd, mtmp, (unsigned) xl + sizeof(struct monst));
292 		if (!mtmp->m_id)
293 			mtmp->m_id = flags.ident++;
294 		mtmp->data = (const struct permonst *)
295 			((const char *) mtmp->data + differ);
296 		if (mtmp->minvent)
297 			mtmp->minvent = restobjchn(fd);
298 		mtmp2 = mtmp;
299 	}
300 	if (first && mtmp2->nmon) {
301 		impossible("Restmonchn: error reading monchn.");
302 		mtmp2->nmon = 0;
303 	}
304 	return (first);
305 }
306