xref: /netbsd/games/hack/hack.save.c (revision fe7fbef8)
1*fe7fbef8Sdholland /*	$NetBSD: hack.save.c,v 1.16 2011/08/06 20:42:43 dholland Exp $	*/
23ea4a95cSchristos 
3210cab45Smycroft /*
41c7f94e5Sjsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm  * Amsterdam
61c7f94e5Sjsm  * All rights reserved.
71c7f94e5Sjsm  *
81c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm  * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm  * met:
111c7f94e5Sjsm  *
121c7f94e5Sjsm  * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm  * this list of conditions and the following disclaimer.
141c7f94e5Sjsm  *
151c7f94e5Sjsm  * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm  * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm  * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm  *
191c7f94e5Sjsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm  * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm  * promote products derived from this software without specific prior
221c7f94e5Sjsm  * written permission.
231c7f94e5Sjsm  *
241c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm  */
361c7f94e5Sjsm 
371c7f94e5Sjsm /*
381c7f94e5Sjsm  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm  * All rights reserved.
401c7f94e5Sjsm  *
411c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm  * modification, are permitted provided that the following conditions
431c7f94e5Sjsm  * are met:
441c7f94e5Sjsm  * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm  * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm  *    documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm  * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm  *    derived from this software without specific prior written permission.
511c7f94e5Sjsm  *
521c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
551c7f94e5Sjsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62210cab45Smycroft  */
63210cab45Smycroft 
643ea4a95cSchristos #include <sys/cdefs.h>
65210cab45Smycroft #ifndef lint
66*fe7fbef8Sdholland __RCSID("$NetBSD: hack.save.c,v 1.16 2011/08/06 20:42:43 dholland Exp $");
67210cab45Smycroft #endif				/* not lint */
6861f28255Scgd 
6961f28255Scgd #include <signal.h>
703ea4a95cSchristos #include <stdlib.h>
7142fb1b9dScgd #include <unistd.h>
723ea4a95cSchristos #include <fcntl.h>
733ea4a95cSchristos #include "hack.h"
743ea4a95cSchristos #include "extern.h"
7561f28255Scgd 
769b92b189Sdholland static int dosave0(int);
7761f28255Scgd 
783ea4a95cSchristos int
dosave(void)791fa8a9a6Sdholland dosave(void)
803ea4a95cSchristos {
8161f28255Scgd 	if (dosave0(0)) {
8261f28255Scgd 		settty("Be seeing you ...\n");
8361f28255Scgd 		exit(0);
8461f28255Scgd 	}
8561f28255Scgd 	return (0);
8661f28255Scgd }
8761f28255Scgd 
8861f28255Scgd #ifndef NOSAVEONHANGUP
893ea4a95cSchristos void
hang_up(int n __unused)9098eb8895Sroy hang_up(int n __unused)
913ea4a95cSchristos {
9261f28255Scgd 	(void) dosave0(1);
9361f28255Scgd 	exit(1);
9461f28255Scgd }
953ea4a95cSchristos #endif	/* NOSAVEONHANGUP */
9661f28255Scgd 
9761f28255Scgd /* returns 1 if save successful */
989b92b189Sdholland static int
dosave0(int hu)991fa8a9a6Sdholland dosave0(int hu)
1003ea4a95cSchristos {
1013ea4a95cSchristos 	int		fd, ofd;
1023ea4a95cSchristos 	int             tmp;	/* not ! */
10361f28255Scgd 
10461f28255Scgd 	(void) signal(SIGHUP, SIG_IGN);
10561f28255Scgd 	(void) signal(SIGINT, SIG_IGN);
10661f28255Scgd 	if ((fd = creat(SAVEF, FMASK)) < 0) {
1073ea4a95cSchristos 		if (!hu)
1083ea4a95cSchristos 			pline("Cannot open save file. (Continue or Quit)");
10961f28255Scgd 		(void) unlink(SAVEF);	/* ab@unido */
11061f28255Scgd 		return (0);
11161f28255Scgd 	}
11261f28255Scgd 	if (flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
11361f28255Scgd 		u.uluck--;	/* and unido!ab */
11461f28255Scgd 	savelev(fd, dlevel);
11561f28255Scgd 	saveobjchn(fd, invent);
11661f28255Scgd 	saveobjchn(fd, fcobj);
11761f28255Scgd 	savemonchn(fd, fallen_down);
11861f28255Scgd 	tmp = getuid();
1198d5216e8Sdholland 	bwrite(fd, &tmp, sizeof tmp);
1208d5216e8Sdholland 	bwrite(fd, &flags, sizeof(struct flag));
1218d5216e8Sdholland 	bwrite(fd, &dlevel, sizeof dlevel);
1228d5216e8Sdholland 	bwrite(fd, &maxdlevel, sizeof maxdlevel);
1238d5216e8Sdholland 	bwrite(fd, &moves, sizeof moves);
1248d5216e8Sdholland 	bwrite(fd, &u, sizeof(struct you));
12561f28255Scgd 	if (u.ustuck)
1268d5216e8Sdholland 		bwrite(fd, &(u.ustuck->m_id), sizeof u.ustuck->m_id);
1278d5216e8Sdholland 	bwrite(fd, pl_character, sizeof pl_character);
1288d5216e8Sdholland 	bwrite(fd, genocided, sizeof genocided);
1298d5216e8Sdholland 	bwrite(fd, fut_geno, sizeof fut_geno);
13061f28255Scgd 	savenames(fd);
13161f28255Scgd 	for (tmp = 1; tmp <= maxdlevel; tmp++) {
13261f28255Scgd 
1333ea4a95cSchristos 		if (tmp == dlevel || !level_exists[tmp])
1343ea4a95cSchristos 			continue;
13561f28255Scgd 		glo(tmp);
136ab8b6343Sjsm 		if ((ofd = open(lock, O_RDONLY)) < 0) {
1373ea4a95cSchristos 			if (!hu)
1383ea4a95cSchristos 				pline("Error while saving: cannot read %s.", lock);
13961f28255Scgd 			(void) close(fd);
14061f28255Scgd 			(void) unlink(SAVEF);
1413ea4a95cSchristos 			if (!hu)
1423ea4a95cSchristos 				done("tricked");
14361f28255Scgd 			return (0);
14461f28255Scgd 		}
14561f28255Scgd 		getlev(ofd, hackpid, tmp);
14661f28255Scgd 		(void) close(ofd);
1478d5216e8Sdholland 		bwrite(fd, &tmp, sizeof tmp);	/* level number */
14861f28255Scgd 		savelev(fd, tmp);	/* actual level */
14961f28255Scgd 		(void) unlink(lock);
15061f28255Scgd 	}
15161f28255Scgd 	(void) close(fd);
15261f28255Scgd 	glo(dlevel);
15361f28255Scgd 	(void) unlink(lock);	/* get rid of current level --jgm */
15461f28255Scgd 	glo(0);
15561f28255Scgd 	(void) unlink(lock);
15661f28255Scgd 	return (1);
15761f28255Scgd }
15861f28255Scgd 
1593ea4a95cSchristos int
dorecover(int fd)1601fa8a9a6Sdholland dorecover(int fd)
16161f28255Scgd {
1623ea4a95cSchristos 	int nfd;
1633ea4a95cSchristos 	int             tmp;	/* not a ! */
16461f28255Scgd 	unsigned        mid;	/* idem */
16561f28255Scgd 	struct obj     *otmp;
16661f28255Scgd 
16761f28255Scgd 	restoring = TRUE;
16861f28255Scgd 	getlev(fd, 0, 0);
16961f28255Scgd 	invent = restobjchn(fd);
17061f28255Scgd 	for (otmp = invent; otmp; otmp = otmp->nobj)
17161f28255Scgd 		if (otmp->owornmask)
17261f28255Scgd 			setworn(otmp, otmp->owornmask);
17361f28255Scgd 	fcobj = restobjchn(fd);
17461f28255Scgd 	fallen_down = restmonchn(fd);
175c8aead89Sdholland 	mread(fd, &tmp, sizeof tmp);
1763c439f43Sdholland 	if (tmp != (int) getuid()) {	/* strange ... */
17761f28255Scgd 		(void) close(fd);
17861f28255Scgd 		(void) unlink(SAVEF);
17961f28255Scgd 		puts("Saved game was not yours.");
18061f28255Scgd 		restoring = FALSE;
18161f28255Scgd 		return (0);
18261f28255Scgd 	}
183c8aead89Sdholland 	mread(fd, &flags, sizeof(struct flag));
184c8aead89Sdholland 	mread(fd, &dlevel, sizeof dlevel);
185c8aead89Sdholland 	mread(fd, &maxdlevel, sizeof maxdlevel);
186c8aead89Sdholland 	mread(fd, &moves, sizeof moves);
187c8aead89Sdholland 	mread(fd, &u, sizeof(struct you));
18861f28255Scgd 	if (u.ustuck)
189c8aead89Sdholland 		mread(fd, &mid, sizeof mid);
190c8aead89Sdholland 	mread(fd, pl_character, sizeof pl_character);
191c8aead89Sdholland 	mread(fd, genocided, sizeof genocided);
192c8aead89Sdholland 	mread(fd, fut_geno, sizeof fut_geno);
19361f28255Scgd 	restnames(fd);
19461f28255Scgd 	while (1) {
195*fe7fbef8Sdholland 		if (read(fd, &tmp, sizeof tmp) != sizeof tmp)
19661f28255Scgd 			break;
19761f28255Scgd 		getlev(fd, 0, tmp);
19861f28255Scgd 		glo(tmp);
19961f28255Scgd 		if ((nfd = creat(lock, FMASK)) < 0)
20061f28255Scgd 			panic("Cannot open temp file %s!\n", lock);
20161f28255Scgd 		savelev(nfd, tmp);
20261f28255Scgd 		(void) close(nfd);
20361f28255Scgd 	}
204ab8b6343Sjsm 	(void) lseek(fd, (off_t) 0, SEEK_SET);
20561f28255Scgd 	getlev(fd, 0, 0);
20661f28255Scgd 	(void) close(fd);
20761f28255Scgd 	(void) unlink(SAVEF);
20861f28255Scgd 	if (Punished) {
20961f28255Scgd 		for (otmp = fobj; otmp; otmp = otmp->nobj)
2103ea4a95cSchristos 			if (otmp->olet == CHAIN_SYM)
2113ea4a95cSchristos 				goto chainfnd;
21261f28255Scgd 		panic("Cannot find the iron chain?");
21361f28255Scgd chainfnd:
21461f28255Scgd 		uchain = otmp;
21561f28255Scgd 		if (!uball) {
21661f28255Scgd 			for (otmp = fobj; otmp; otmp = otmp->nobj)
21761f28255Scgd 				if (otmp->olet == BALL_SYM && otmp->spe)
21861f28255Scgd 					goto ballfnd;
21961f28255Scgd 			panic("Cannot find the iron ball?");
22061f28255Scgd 	ballfnd:
22161f28255Scgd 			uball = otmp;
22261f28255Scgd 		}
22361f28255Scgd 	}
22461f28255Scgd 	if (u.ustuck) {
2253ea4a95cSchristos 		struct monst   *mtmp;
22661f28255Scgd 
22761f28255Scgd 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
2283ea4a95cSchristos 			if (mtmp->m_id == mid)
2293ea4a95cSchristos 				goto monfnd;
23061f28255Scgd 		panic("Cannot find the monster ustuck.");
23161f28255Scgd monfnd:
23261f28255Scgd 		u.ustuck = mtmp;
23361f28255Scgd 	}
23461f28255Scgd #ifndef QUEST
2353ea4a95cSchristos 	setsee();		/* only to recompute seelx etc. - these
2363ea4a95cSchristos 				 * weren't saved */
2373ea4a95cSchristos #endif	/* QUEST */
23861f28255Scgd 	docrt();
23961f28255Scgd 	restoring = FALSE;
24061f28255Scgd 	return (1);
24161f28255Scgd }
24261f28255Scgd 
24361f28255Scgd struct obj     *
restobjchn(int fd)2441fa8a9a6Sdholland restobjchn(int fd)
24561f28255Scgd {
2463ea4a95cSchristos 	struct obj     *otmp, *otmp2 = NULL;
2473ea4a95cSchristos 	struct obj     *first = 0;
24861f28255Scgd 	int             xl;
24961f28255Scgd 	while (1) {
250c8aead89Sdholland 		mread(fd, &xl, sizeof(xl));
2513ea4a95cSchristos 		if (xl == -1)
2523ea4a95cSchristos 			break;
25361f28255Scgd 		otmp = newobj(xl);
2543ea4a95cSchristos 		if (!first)
2553ea4a95cSchristos 			first = otmp;
2563ea4a95cSchristos 		else
2573ea4a95cSchristos 			otmp2->nobj = otmp;
258c8aead89Sdholland 		mread(fd, otmp, (unsigned) xl + sizeof(struct obj));
2593ea4a95cSchristos 		if (!otmp->o_id)
2603ea4a95cSchristos 			otmp->o_id = flags.ident++;
26161f28255Scgd 		otmp2 = otmp;
26261f28255Scgd 	}
26361f28255Scgd 	if (first && otmp2->nobj) {
26461f28255Scgd 		impossible("Restobjchn: error reading objchn.");
26561f28255Scgd 		otmp2->nobj = 0;
26661f28255Scgd 	}
26761f28255Scgd 	return (first);
26861f28255Scgd }
26961f28255Scgd 
27061f28255Scgd struct monst   *
restmonchn(int fd)2711fa8a9a6Sdholland restmonchn(int fd)
27261f28255Scgd {
2733ea4a95cSchristos 	struct monst   *mtmp, *mtmp2 = NULL;
2743ea4a95cSchristos 	struct monst   *first = 0;
27561f28255Scgd 	int             xl;
27661f28255Scgd 
27761f28255Scgd 	struct permonst *monbegin;
27861f28255Scgd 	long            differ;
27961f28255Scgd 
280c8aead89Sdholland 	mread(fd, &monbegin, sizeof(monbegin));
281ab8b6343Sjsm 	differ = (const char *) (&mons[0]) - (const char *) (monbegin);
28261f28255Scgd 
28361f28255Scgd #ifdef lint
28461f28255Scgd 	/* suppress "used before set" warning from lint */
28561f28255Scgd 	mtmp2 = 0;
2863ea4a95cSchristos #endif	/* lint */
28761f28255Scgd 	while (1) {
288c8aead89Sdholland 		mread(fd, &xl, sizeof(xl));
2893ea4a95cSchristos 		if (xl == -1)
2903ea4a95cSchristos 			break;
29161f28255Scgd 		mtmp = newmonst(xl);
2923ea4a95cSchristos 		if (!first)
2933ea4a95cSchristos 			first = mtmp;
2943ea4a95cSchristos 		else
2953ea4a95cSchristos 			mtmp2->nmon = mtmp;
296c8aead89Sdholland 		mread(fd, mtmp, (unsigned) xl + sizeof(struct monst));
29761f28255Scgd 		if (!mtmp->m_id)
29861f28255Scgd 			mtmp->m_id = flags.ident++;
299ab8b6343Sjsm 		mtmp->data = (const struct permonst *)
300ab8b6343Sjsm 			((const char *) mtmp->data + differ);
30161f28255Scgd 		if (mtmp->minvent)
30261f28255Scgd 			mtmp->minvent = restobjchn(fd);
30361f28255Scgd 		mtmp2 = mtmp;
30461f28255Scgd 	}
30561f28255Scgd 	if (first && mtmp2->nmon) {
30661f28255Scgd 		impossible("Restmonchn: error reading monchn.");
30761f28255Scgd 		mtmp2->nmon = 0;
30861f28255Scgd 	}
30961f28255Scgd 	return (first);
31061f28255Scgd }
311