xref: /netbsd/games/hack/hack.lev.c (revision 3c439f43)
1 /*	$NetBSD: hack.lev.c,v 1.7 2008/01/28 06:55:41 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 <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.lev.c,v 1.7 2008/01/28 06:55:41 dholland Exp $");
67 #endif				/* not lint */
68 
69 #include <stdlib.h>
70 #include <unistd.h>
71 #include "hack.h"
72 #include "extern.h"
73 #include "def.mkroom.h"
74 
75 #ifndef NOWORM
76 #include	"def.wseg.h"
77 #endif				/* NOWORM */
78 
79 boolean         level_exists[MAXLEVEL + 1];
80 
81 void
82 savelev(fd, lev)
83 	int             fd;
84 	xchar           lev;
85 {
86 #ifndef NOWORM
87 	struct wseg    *wtmp, *wtmp2;
88 	int tmp;
89 #endif	/* NOWORM */
90 
91 	if (fd < 0)
92 		panic("Save on bad file!");	/* impossible */
93 	if (lev >= 0 && lev <= MAXLEVEL)
94 		level_exists[lev] = TRUE;
95 
96 	bwrite(fd, (char *) &hackpid, sizeof(hackpid));
97 	bwrite(fd, (char *) &lev, sizeof(lev));
98 	bwrite(fd, (char *) levl, sizeof(levl));
99 	bwrite(fd, (char *) &moves, sizeof(long));
100 	bwrite(fd, (char *) &xupstair, sizeof(xupstair));
101 	bwrite(fd, (char *) &yupstair, sizeof(yupstair));
102 	bwrite(fd, (char *) &xdnstair, sizeof(xdnstair));
103 	bwrite(fd, (char *) &ydnstair, sizeof(ydnstair));
104 	savemonchn(fd, fmon);
105 	savegoldchn(fd, fgold);
106 	savetrapchn(fd, ftrap);
107 	saveobjchn(fd, fobj);
108 	saveobjchn(fd, billobjs);
109 	billobjs = 0;
110 	save_engravings(fd);
111 #ifndef QUEST
112 	bwrite(fd, (char *) rooms, sizeof(rooms));
113 	bwrite(fd, (char *) doors, sizeof(doors));
114 #endif	/* QUEST */
115 	fgold = 0;
116 	ftrap = 0;
117 	fmon = 0;
118 	fobj = 0;
119 #ifndef NOWORM
120 	bwrite(fd, (char *) wsegs, sizeof(wsegs));
121 	for (tmp = 1; tmp < 32; tmp++) {
122 		for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
123 			wtmp2 = wtmp->nseg;
124 			bwrite(fd, (char *) wtmp, sizeof(struct wseg));
125 		}
126 		wsegs[tmp] = 0;
127 	}
128 	bwrite(fd, (char *) wgrowtime, sizeof(wgrowtime));
129 #endif	/* NOWORM */
130 }
131 
132 void
133 bwrite(fd, loc, num)
134 	int fd;
135 	const void     *loc;
136 	unsigned        num;
137 {
138 	/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
139 	if (write(fd, loc, (int) num) != num)
140 		panic("cannot write %u bytes to file #%d", num, fd);
141 }
142 
143 void
144 saveobjchn(fd, otmp)
145 	int fd;
146 	struct obj     *otmp;
147 {
148 	struct obj     *otmp2;
149 	unsigned        xl;
150 	int             minusone = -1;
151 
152 	while (otmp) {
153 		otmp2 = otmp->nobj;
154 		xl = otmp->onamelth;
155 		bwrite(fd, (char *) &xl, sizeof(int));
156 		bwrite(fd, (char *) otmp, xl + sizeof(struct obj));
157 		free((char *) otmp);
158 		otmp = otmp2;
159 	}
160 	bwrite(fd, (char *) &minusone, sizeof(int));
161 }
162 
163 void
164 savemonchn(fd, mtmp)
165 	int fd;
166 	struct monst   *mtmp;
167 {
168 	struct monst   *mtmp2;
169 	unsigned        xl;
170 	int             minusone = -1;
171 	const struct permonst *monbegin = &mons[0];
172 
173 	bwrite(fd, &monbegin, sizeof(monbegin));
174 
175 	while (mtmp) {
176 		mtmp2 = mtmp->nmon;
177 		xl = mtmp->mxlth + mtmp->mnamelth;
178 		bwrite(fd, (char *) &xl, sizeof(int));
179 		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
180 		if (mtmp->minvent)
181 			saveobjchn(fd, mtmp->minvent);
182 		free((char *) mtmp);
183 		mtmp = mtmp2;
184 	}
185 	bwrite(fd, (char *) &minusone, sizeof(int));
186 }
187 
188 void
189 savegoldchn(fd, gold)
190 	int fd;
191 	struct gold    *gold;
192 {
193 	struct gold    *gold2;
194 	while (gold) {
195 		gold2 = gold->ngold;
196 		bwrite(fd, (char *) gold, sizeof(struct gold));
197 		free((char *) gold);
198 		gold = gold2;
199 	}
200 	bwrite(fd, nul, sizeof(struct gold));
201 }
202 
203 void
204 savetrapchn(fd, trap)
205 	int fd;
206 	struct trap    *trap;
207 {
208 	struct trap    *trap2;
209 	while (trap) {
210 		trap2 = trap->ntrap;
211 		bwrite(fd, (char *) trap, sizeof(struct trap));
212 		free((char *) trap);
213 		trap = trap2;
214 	}
215 	bwrite(fd, nul, sizeof(struct trap));
216 }
217 
218 void
219 getlev(fd, pid, lev)
220 	int             fd, pid;
221 	xchar           lev;
222 {
223 	struct gold    *gold;
224 	struct trap    *trap;
225 #ifndef NOWORM
226 	struct wseg    *wtmp;
227 #endif	/* NOWORM */
228 	int		tmp;
229 	long            omoves;
230 	int             hpid;
231 	xchar           dlvl;
232 
233 	/* First some sanity checks */
234 	mread(fd, (char *) &hpid, sizeof(hpid));
235 	mread(fd, (char *) &dlvl, sizeof(dlvl));
236 	if ((pid && pid != hpid) || (lev && dlvl != lev)) {
237 		pline("Strange, this map is not as I remember it.");
238 		pline("Somebody is trying some trickery here ...");
239 		pline("This game is void ...");
240 		done("tricked");
241 	}
242 	fgold = 0;
243 	ftrap = 0;
244 	mread(fd, (char *) levl, sizeof(levl));
245 	mread(fd, (char *) &omoves, sizeof(omoves));
246 	mread(fd, (char *) &xupstair, sizeof(xupstair));
247 	mread(fd, (char *) &yupstair, sizeof(yupstair));
248 	mread(fd, (char *) &xdnstair, sizeof(xdnstair));
249 	mread(fd, (char *) &ydnstair, sizeof(ydnstair));
250 
251 	fmon = restmonchn(fd);
252 
253 	/* regenerate animals while on another level */
254 	{
255 		long            tmoves = (moves > omoves) ? moves - omoves : 0;
256 		struct monst   *mtmp, *mtmp2;
257 
258 		for (mtmp = fmon; mtmp; mtmp = mtmp2) {
259 			long            newhp;	/* tmoves may be very large */
260 
261 			mtmp2 = mtmp->nmon;
262 			if (strchr(genocided, mtmp->data->mlet)) {
263 				mondead(mtmp);
264 				continue;
265 			}
266 			if (mtmp->mtame && tmoves > 250) {
267 				mtmp->mtame = 0;
268 				mtmp->mpeaceful = 0;
269 			}
270 			newhp = mtmp->mhp +
271 				(strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20);
272 			if (newhp > mtmp->mhpmax)
273 				mtmp->mhp = mtmp->mhpmax;
274 			else
275 				mtmp->mhp = newhp;
276 		}
277 	}
278 
279 	setgd();
280 	gold = newgold();
281 	mread(fd, (char *) gold, sizeof(struct gold));
282 	while (gold->gx) {
283 		gold->ngold = fgold;
284 		fgold = gold;
285 		gold = newgold();
286 		mread(fd, (char *) gold, sizeof(struct gold));
287 	}
288 	free((char *) gold);
289 	trap = newtrap();
290 	mread(fd, (char *) trap, sizeof(struct trap));
291 	while (trap->tx) {
292 		trap->ntrap = ftrap;
293 		ftrap = trap;
294 		trap = newtrap();
295 		mread(fd, (char *) trap, sizeof(struct trap));
296 	}
297 	free((char *) trap);
298 	fobj = restobjchn(fd);
299 	billobjs = restobjchn(fd);
300 	rest_engravings(fd);
301 #ifndef QUEST
302 	mread(fd, (char *) rooms, sizeof(rooms));
303 	mread(fd, (char *) doors, sizeof(doors));
304 #endif	/* QUEST */
305 #ifndef NOWORM
306 	mread(fd, (char *) wsegs, sizeof(wsegs));
307 	for (tmp = 1; tmp < 32; tmp++)
308 		if (wsegs[tmp]) {
309 			wheads[tmp] = wsegs[tmp] = wtmp = newseg();
310 			while (1) {
311 				mread(fd, (char *) wtmp, sizeof(struct wseg));
312 				if (!wtmp->nseg)
313 					break;
314 				wheads[tmp]->nseg = wtmp = newseg();
315 				wheads[tmp] = wtmp;
316 			}
317 		}
318 	mread(fd, (char *) wgrowtime, sizeof(wgrowtime));
319 #endif	/* NOWORM */
320 }
321 
322 void
323 mread(fd, buf, len)
324 	int fd;
325 	char           *buf;
326 	unsigned        len;
327 {
328 	int             rlen;
329 
330 	rlen = read(fd, buf, len);
331 	if (rlen < 0 || (size_t)rlen != len) {
332 		pline("Read %d instead of %u bytes.\n", rlen, len);
333 		if (restoring) {
334 			(void) unlink(SAVEF);
335 			error("Error restoring old game.");
336 		}
337 		panic("Error reading level file.");
338 	}
339 }
340 
341 void
342 mklev()
343 {
344 	if (getbones())
345 		return;
346 
347 	in_mklev = TRUE;
348 	makelevel();
349 	in_mklev = FALSE;
350 }
351