xref: /netbsd-src/games/hack/hack.lev.c (revision 8041af98f6782a401d6fd4846e034ec2ddf14b58)
1*8041af98Sdholland /*	$NetBSD: hack.lev.c,v 1.14 2011/08/06 20:32:25 dholland Exp $	*/
23ea4a95cSchristos 
302ded532Smycroft /*
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.
6202ded532Smycroft  */
6302ded532Smycroft 
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*8041af98Sdholland __RCSID("$NetBSD: hack.lev.c,v 1.14 2011/08/06 20:32:25 dholland Exp $");
6702ded532Smycroft #endif				/* not lint */
6861f28255Scgd 
693ea4a95cSchristos #include <stdlib.h>
703ea4a95cSchristos #include <unistd.h>
7161f28255Scgd #include "hack.h"
723ea4a95cSchristos #include "extern.h"
7361f28255Scgd #include "def.mkroom.h"
7461f28255Scgd 
7561f28255Scgd #ifndef NOWORM
7661f28255Scgd #include	"def.wseg.h"
773ea4a95cSchristos #endif				/* NOWORM */
7861f28255Scgd 
7961f28255Scgd boolean         level_exists[MAXLEVEL + 1];
8061f28255Scgd 
819b92b189Sdholland static void savegoldchn(int, struct gold *);
829b92b189Sdholland static void savetrapchn(int, struct trap *);
839b92b189Sdholland 
843ea4a95cSchristos void
savelev(int fd,xchar lev)851fa8a9a6Sdholland savelev(int fd, xchar lev)
8661f28255Scgd {
8761f28255Scgd #ifndef NOWORM
883ea4a95cSchristos 	struct wseg    *wtmp, *wtmp2;
893ea4a95cSchristos 	int tmp;
903ea4a95cSchristos #endif	/* NOWORM */
9161f28255Scgd 
923ea4a95cSchristos 	if (fd < 0)
933ea4a95cSchristos 		panic("Save on bad file!");	/* impossible */
9461f28255Scgd 	if (lev >= 0 && lev <= MAXLEVEL)
9561f28255Scgd 		level_exists[lev] = TRUE;
9661f28255Scgd 
97*8041af98Sdholland 	bwrite(fd, &hackpid, sizeof(hackpid));
98*8041af98Sdholland 	bwrite(fd, &lev, sizeof(lev));
99*8041af98Sdholland 	bwrite(fd, levl, sizeof(levl));
100*8041af98Sdholland 	bwrite(fd, &moves, sizeof(long));
101*8041af98Sdholland 	bwrite(fd, &xupstair, sizeof(xupstair));
102*8041af98Sdholland 	bwrite(fd, &yupstair, sizeof(yupstair));
103*8041af98Sdholland 	bwrite(fd, &xdnstair, sizeof(xdnstair));
104*8041af98Sdholland 	bwrite(fd, &ydnstair, sizeof(ydnstair));
10561f28255Scgd 	savemonchn(fd, fmon);
10661f28255Scgd 	savegoldchn(fd, fgold);
10761f28255Scgd 	savetrapchn(fd, ftrap);
10861f28255Scgd 	saveobjchn(fd, fobj);
10961f28255Scgd 	saveobjchn(fd, billobjs);
11061f28255Scgd 	billobjs = 0;
11161f28255Scgd 	save_engravings(fd);
11261f28255Scgd #ifndef QUEST
113*8041af98Sdholland 	bwrite(fd, rooms, sizeof(rooms));
114*8041af98Sdholland 	bwrite(fd, doors, sizeof(doors));
1153ea4a95cSchristos #endif	/* QUEST */
11661f28255Scgd 	fgold = 0;
11761f28255Scgd 	ftrap = 0;
11861f28255Scgd 	fmon = 0;
11961f28255Scgd 	fobj = 0;
12061f28255Scgd #ifndef NOWORM
121*8041af98Sdholland 	bwrite(fd, wsegs, sizeof(wsegs));
12261f28255Scgd 	for (tmp = 1; tmp < 32; tmp++) {
12361f28255Scgd 		for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
12461f28255Scgd 			wtmp2 = wtmp->nseg;
125*8041af98Sdholland 			bwrite(fd, wtmp, sizeof(struct wseg));
12661f28255Scgd 		}
12761f28255Scgd 		wsegs[tmp] = 0;
12861f28255Scgd 	}
129*8041af98Sdholland 	bwrite(fd, wgrowtime, sizeof(wgrowtime));
1303ea4a95cSchristos #endif	/* NOWORM */
13161f28255Scgd }
13261f28255Scgd 
1333ea4a95cSchristos void
bwrite(int fd,const void * loc,size_t num)1341fa8a9a6Sdholland bwrite(int fd, const void *loc, size_t num)
13561f28255Scgd {
13661f28255Scgd 	/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
137c6144e48Slukem 	if ((size_t)write(fd, loc, num) != num)
138f341bbffStnn 		panic("cannot write %zu bytes to file #%d", num, fd);
13961f28255Scgd }
14061f28255Scgd 
1413ea4a95cSchristos void
saveobjchn(int fd,struct obj * otmp)1421fa8a9a6Sdholland saveobjchn(int fd, struct obj *otmp)
14361f28255Scgd {
1443ea4a95cSchristos 	struct obj     *otmp2;
14561f28255Scgd 	unsigned        xl;
14661f28255Scgd 	int             minusone = -1;
14761f28255Scgd 
14861f28255Scgd 	while (otmp) {
14961f28255Scgd 		otmp2 = otmp->nobj;
15061f28255Scgd 		xl = otmp->onamelth;
151*8041af98Sdholland 		bwrite(fd, &xl, sizeof(int));
152*8041af98Sdholland 		bwrite(fd, otmp, xl + sizeof(struct obj));
1538e73b3adSdholland 		free(otmp);
15461f28255Scgd 		otmp = otmp2;
15561f28255Scgd 	}
156*8041af98Sdholland 	bwrite(fd, &minusone, sizeof(int));
15761f28255Scgd }
15861f28255Scgd 
1593ea4a95cSchristos void
savemonchn(int fd,struct monst * mtmp)1601fa8a9a6Sdholland savemonchn(int fd, struct monst *mtmp)
16161f28255Scgd {
1623ea4a95cSchristos 	struct monst   *mtmp2;
16361f28255Scgd 	unsigned        xl;
16461f28255Scgd 	int             minusone = -1;
165ab8b6343Sjsm 	const struct permonst *monbegin = &mons[0];
16661f28255Scgd 
167ab8b6343Sjsm 	bwrite(fd, &monbegin, sizeof(monbegin));
16861f28255Scgd 
16961f28255Scgd 	while (mtmp) {
17061f28255Scgd 		mtmp2 = mtmp->nmon;
17161f28255Scgd 		xl = mtmp->mxlth + mtmp->mnamelth;
172*8041af98Sdholland 		bwrite(fd, &xl, sizeof(int));
173*8041af98Sdholland 		bwrite(fd, mtmp, xl + sizeof(struct monst));
1743ea4a95cSchristos 		if (mtmp->minvent)
1753ea4a95cSchristos 			saveobjchn(fd, mtmp->minvent);
1768e73b3adSdholland 		free(mtmp);
17761f28255Scgd 		mtmp = mtmp2;
17861f28255Scgd 	}
179*8041af98Sdholland 	bwrite(fd, &minusone, sizeof(int));
18061f28255Scgd }
18161f28255Scgd 
1829b92b189Sdholland static void
savegoldchn(int fd,struct gold * gold)1831fa8a9a6Sdholland savegoldchn(int fd, struct gold *gold)
18461f28255Scgd {
1853ea4a95cSchristos 	struct gold    *gold2;
18661f28255Scgd 	while (gold) {
18761f28255Scgd 		gold2 = gold->ngold;
188*8041af98Sdholland 		bwrite(fd, gold, sizeof(struct gold));
1898e73b3adSdholland 		free(gold);
19061f28255Scgd 		gold = gold2;
19161f28255Scgd 	}
19261f28255Scgd 	bwrite(fd, nul, sizeof(struct gold));
19361f28255Scgd }
19461f28255Scgd 
1959b92b189Sdholland static void
savetrapchn(int fd,struct trap * trap)1961fa8a9a6Sdholland savetrapchn(int fd, struct trap *trap)
19761f28255Scgd {
1983ea4a95cSchristos 	struct trap    *trap2;
19961f28255Scgd 	while (trap) {
20061f28255Scgd 		trap2 = trap->ntrap;
201*8041af98Sdholland 		bwrite(fd, trap, sizeof(struct trap));
2028e73b3adSdholland 		free(trap);
20361f28255Scgd 		trap = trap2;
20461f28255Scgd 	}
20561f28255Scgd 	bwrite(fd, nul, sizeof(struct trap));
20661f28255Scgd }
20761f28255Scgd 
2083ea4a95cSchristos void
getlev(int fd,int pid,xchar lev)2091fa8a9a6Sdholland getlev(int fd, int pid, xchar lev)
21061f28255Scgd {
2113ea4a95cSchristos 	struct gold    *gold;
2123ea4a95cSchristos 	struct trap    *trap;
21361f28255Scgd #ifndef NOWORM
2143ea4a95cSchristos 	struct wseg    *wtmp;
2153ea4a95cSchristos #endif	/* NOWORM */
2163ea4a95cSchristos 	int		tmp;
21761f28255Scgd 	long            omoves;
21861f28255Scgd 	int             hpid;
21961f28255Scgd 	xchar           dlvl;
22061f28255Scgd 
22161f28255Scgd 	/* First some sanity checks */
22225ec2965Sdholland 	mread(fd, &hpid, sizeof(hpid));
22325ec2965Sdholland 	mread(fd, &dlvl, sizeof(dlvl));
22461f28255Scgd 	if ((pid && pid != hpid) || (lev && dlvl != lev)) {
22561f28255Scgd 		pline("Strange, this map is not as I remember it.");
22661f28255Scgd 		pline("Somebody is trying some trickery here ...");
22761f28255Scgd 		pline("This game is void ...");
22861f28255Scgd 		done("tricked");
22961f28255Scgd 	}
23061f28255Scgd 	fgold = 0;
23161f28255Scgd 	ftrap = 0;
23225ec2965Sdholland 	mread(fd, levl, sizeof(levl));
23325ec2965Sdholland 	mread(fd, &omoves, sizeof(omoves));
23425ec2965Sdholland 	mread(fd, &xupstair, sizeof(xupstair));
23525ec2965Sdholland 	mread(fd, &yupstair, sizeof(yupstair));
23625ec2965Sdholland 	mread(fd, &xdnstair, sizeof(xdnstair));
23725ec2965Sdholland 	mread(fd, &ydnstair, sizeof(ydnstair));
23861f28255Scgd 
23961f28255Scgd 	fmon = restmonchn(fd);
24061f28255Scgd 
24161f28255Scgd 	/* regenerate animals while on another level */
2423ea4a95cSchristos 	{
2433ea4a95cSchristos 		long            tmoves = (moves > omoves) ? moves - omoves : 0;
2443ea4a95cSchristos 		struct monst   *mtmp, *mtmp2;
24561f28255Scgd 
24661f28255Scgd 		for (mtmp = fmon; mtmp; mtmp = mtmp2) {
24761f28255Scgd 			long            newhp;	/* tmoves may be very large */
24861f28255Scgd 
24961f28255Scgd 			mtmp2 = mtmp->nmon;
2503ea4a95cSchristos 			if (strchr(genocided, mtmp->data->mlet)) {
25161f28255Scgd 				mondead(mtmp);
25261f28255Scgd 				continue;
25361f28255Scgd 			}
25461f28255Scgd 			if (mtmp->mtame && tmoves > 250) {
25561f28255Scgd 				mtmp->mtame = 0;
25661f28255Scgd 				mtmp->mpeaceful = 0;
25761f28255Scgd 			}
25861f28255Scgd 			newhp = mtmp->mhp +
2593ea4a95cSchristos 				(strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20);
26061f28255Scgd 			if (newhp > mtmp->mhpmax)
26161f28255Scgd 				mtmp->mhp = mtmp->mhpmax;
26261f28255Scgd 			else
26361f28255Scgd 				mtmp->mhp = newhp;
26461f28255Scgd 		}
26561f28255Scgd 	}
26661f28255Scgd 
26761f28255Scgd 	setgd();
26861f28255Scgd 	gold = newgold();
26925ec2965Sdholland 	mread(fd, gold, sizeof(struct gold));
27061f28255Scgd 	while (gold->gx) {
27161f28255Scgd 		gold->ngold = fgold;
27261f28255Scgd 		fgold = gold;
27361f28255Scgd 		gold = newgold();
27425ec2965Sdholland 		mread(fd, gold, sizeof(struct gold));
27561f28255Scgd 	}
2768e73b3adSdholland 	free(gold);
27761f28255Scgd 	trap = newtrap();
27825ec2965Sdholland 	mread(fd, trap, sizeof(struct trap));
27961f28255Scgd 	while (trap->tx) {
28061f28255Scgd 		trap->ntrap = ftrap;
28161f28255Scgd 		ftrap = trap;
28261f28255Scgd 		trap = newtrap();
28325ec2965Sdholland 		mread(fd, trap, sizeof(struct trap));
28461f28255Scgd 	}
2858e73b3adSdholland 	free(trap);
28661f28255Scgd 	fobj = restobjchn(fd);
28761f28255Scgd 	billobjs = restobjchn(fd);
28861f28255Scgd 	rest_engravings(fd);
28961f28255Scgd #ifndef QUEST
29025ec2965Sdholland 	mread(fd, rooms, sizeof(rooms));
29125ec2965Sdholland 	mread(fd, doors, sizeof(doors));
2923ea4a95cSchristos #endif	/* QUEST */
29361f28255Scgd #ifndef NOWORM
29425ec2965Sdholland 	mread(fd, wsegs, sizeof(wsegs));
2953ea4a95cSchristos 	for (tmp = 1; tmp < 32; tmp++)
2963ea4a95cSchristos 		if (wsegs[tmp]) {
29761f28255Scgd 			wheads[tmp] = wsegs[tmp] = wtmp = newseg();
29861f28255Scgd 			while (1) {
29925ec2965Sdholland 				mread(fd, wtmp, sizeof(struct wseg));
3003ea4a95cSchristos 				if (!wtmp->nseg)
3013ea4a95cSchristos 					break;
30261f28255Scgd 				wheads[tmp]->nseg = wtmp = newseg();
30361f28255Scgd 				wheads[tmp] = wtmp;
30461f28255Scgd 			}
30561f28255Scgd 		}
30625ec2965Sdholland 	mread(fd, wgrowtime, sizeof(wgrowtime));
3073ea4a95cSchristos #endif	/* NOWORM */
30861f28255Scgd }
30961f28255Scgd 
3103ea4a95cSchristos void
mread(int fd,void * buf,size_t len)31125ec2965Sdholland mread(int fd, void *buf, size_t len)
31261f28255Scgd {
31325ec2965Sdholland 	ssize_t rlen;
31461f28255Scgd 
3153c439f43Sdholland 	rlen = read(fd, buf, len);
3163c439f43Sdholland 	if (rlen < 0 || (size_t)rlen != len) {
31725ec2965Sdholland 		pline("Read %zd instead of %zu bytes.\n", rlen, len);
31861f28255Scgd 		if (restoring) {
31961f28255Scgd 			(void) unlink(SAVEF);
32061f28255Scgd 			error("Error restoring old game.");
32161f28255Scgd 		}
32261f28255Scgd 		panic("Error reading level file.");
32361f28255Scgd 	}
32461f28255Scgd }
32561f28255Scgd 
3263ea4a95cSchristos void
mklev(void)3271fa8a9a6Sdholland mklev(void)
32861f28255Scgd {
3293ea4a95cSchristos 	if (getbones())
3303ea4a95cSchristos 		return;
33161f28255Scgd 
33261f28255Scgd 	in_mklev = TRUE;
33361f28255Scgd 	makelevel();
33461f28255Scgd 	in_mklev = FALSE;
33561f28255Scgd }
336