xref: /netbsd/games/hack/hack.lev.c (revision bf9ec67e)
1 /*	$NetBSD: hack.lev.c,v 1.5 2001/03/25 20:44:01 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.lev.c,v 1.5 2001/03/25 20:44:01 jsm Exp $");
10 #endif				/* not lint */
11 
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include "hack.h"
15 #include "extern.h"
16 #include "def.mkroom.h"
17 
18 #ifndef NOWORM
19 #include	"def.wseg.h"
20 #endif				/* NOWORM */
21 
22 boolean         level_exists[MAXLEVEL + 1];
23 
24 void
25 savelev(fd, lev)
26 	int             fd;
27 	xchar           lev;
28 {
29 #ifndef NOWORM
30 	struct wseg    *wtmp, *wtmp2;
31 	int tmp;
32 #endif	/* NOWORM */
33 
34 	if (fd < 0)
35 		panic("Save on bad file!");	/* impossible */
36 	if (lev >= 0 && lev <= MAXLEVEL)
37 		level_exists[lev] = TRUE;
38 
39 	bwrite(fd, (char *) &hackpid, sizeof(hackpid));
40 	bwrite(fd, (char *) &lev, sizeof(lev));
41 	bwrite(fd, (char *) levl, sizeof(levl));
42 	bwrite(fd, (char *) &moves, sizeof(long));
43 	bwrite(fd, (char *) &xupstair, sizeof(xupstair));
44 	bwrite(fd, (char *) &yupstair, sizeof(yupstair));
45 	bwrite(fd, (char *) &xdnstair, sizeof(xdnstair));
46 	bwrite(fd, (char *) &ydnstair, sizeof(ydnstair));
47 	savemonchn(fd, fmon);
48 	savegoldchn(fd, fgold);
49 	savetrapchn(fd, ftrap);
50 	saveobjchn(fd, fobj);
51 	saveobjchn(fd, billobjs);
52 	billobjs = 0;
53 	save_engravings(fd);
54 #ifndef QUEST
55 	bwrite(fd, (char *) rooms, sizeof(rooms));
56 	bwrite(fd, (char *) doors, sizeof(doors));
57 #endif	/* QUEST */
58 	fgold = 0;
59 	ftrap = 0;
60 	fmon = 0;
61 	fobj = 0;
62 #ifndef NOWORM
63 	bwrite(fd, (char *) wsegs, sizeof(wsegs));
64 	for (tmp = 1; tmp < 32; tmp++) {
65 		for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
66 			wtmp2 = wtmp->nseg;
67 			bwrite(fd, (char *) wtmp, sizeof(struct wseg));
68 		}
69 		wsegs[tmp] = 0;
70 	}
71 	bwrite(fd, (char *) wgrowtime, sizeof(wgrowtime));
72 #endif	/* NOWORM */
73 }
74 
75 void
76 bwrite(fd, loc, num)
77 	int fd;
78 	const void     *loc;
79 	unsigned        num;
80 {
81 	/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
82 	if (write(fd, loc, (int) num) != num)
83 		panic("cannot write %u bytes to file #%d", num, fd);
84 }
85 
86 void
87 saveobjchn(fd, otmp)
88 	int fd;
89 	struct obj     *otmp;
90 {
91 	struct obj     *otmp2;
92 	unsigned        xl;
93 	int             minusone = -1;
94 
95 	while (otmp) {
96 		otmp2 = otmp->nobj;
97 		xl = otmp->onamelth;
98 		bwrite(fd, (char *) &xl, sizeof(int));
99 		bwrite(fd, (char *) otmp, xl + sizeof(struct obj));
100 		free((char *) otmp);
101 		otmp = otmp2;
102 	}
103 	bwrite(fd, (char *) &minusone, sizeof(int));
104 }
105 
106 void
107 savemonchn(fd, mtmp)
108 	int fd;
109 	struct monst   *mtmp;
110 {
111 	struct monst   *mtmp2;
112 	unsigned        xl;
113 	int             minusone = -1;
114 	const struct permonst *monbegin = &mons[0];
115 
116 	bwrite(fd, &monbegin, sizeof(monbegin));
117 
118 	while (mtmp) {
119 		mtmp2 = mtmp->nmon;
120 		xl = mtmp->mxlth + mtmp->mnamelth;
121 		bwrite(fd, (char *) &xl, sizeof(int));
122 		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
123 		if (mtmp->minvent)
124 			saveobjchn(fd, mtmp->minvent);
125 		free((char *) mtmp);
126 		mtmp = mtmp2;
127 	}
128 	bwrite(fd, (char *) &minusone, sizeof(int));
129 }
130 
131 void
132 savegoldchn(fd, gold)
133 	int fd;
134 	struct gold    *gold;
135 {
136 	struct gold    *gold2;
137 	while (gold) {
138 		gold2 = gold->ngold;
139 		bwrite(fd, (char *) gold, sizeof(struct gold));
140 		free((char *) gold);
141 		gold = gold2;
142 	}
143 	bwrite(fd, nul, sizeof(struct gold));
144 }
145 
146 void
147 savetrapchn(fd, trap)
148 	int fd;
149 	struct trap    *trap;
150 {
151 	struct trap    *trap2;
152 	while (trap) {
153 		trap2 = trap->ntrap;
154 		bwrite(fd, (char *) trap, sizeof(struct trap));
155 		free((char *) trap);
156 		trap = trap2;
157 	}
158 	bwrite(fd, nul, sizeof(struct trap));
159 }
160 
161 void
162 getlev(fd, pid, lev)
163 	int             fd, pid;
164 	xchar           lev;
165 {
166 	struct gold    *gold;
167 	struct trap    *trap;
168 #ifndef NOWORM
169 	struct wseg    *wtmp;
170 #endif	/* NOWORM */
171 	int		tmp;
172 	long            omoves;
173 	int             hpid;
174 	xchar           dlvl;
175 
176 	/* First some sanity checks */
177 	mread(fd, (char *) &hpid, sizeof(hpid));
178 	mread(fd, (char *) &dlvl, sizeof(dlvl));
179 	if ((pid && pid != hpid) || (lev && dlvl != lev)) {
180 		pline("Strange, this map is not as I remember it.");
181 		pline("Somebody is trying some trickery here ...");
182 		pline("This game is void ...");
183 		done("tricked");
184 	}
185 	fgold = 0;
186 	ftrap = 0;
187 	mread(fd, (char *) levl, sizeof(levl));
188 	mread(fd, (char *) &omoves, sizeof(omoves));
189 	mread(fd, (char *) &xupstair, sizeof(xupstair));
190 	mread(fd, (char *) &yupstair, sizeof(yupstair));
191 	mread(fd, (char *) &xdnstair, sizeof(xdnstair));
192 	mread(fd, (char *) &ydnstair, sizeof(ydnstair));
193 
194 	fmon = restmonchn(fd);
195 
196 	/* regenerate animals while on another level */
197 	{
198 		long            tmoves = (moves > omoves) ? moves - omoves : 0;
199 		struct monst   *mtmp, *mtmp2;
200 
201 		for (mtmp = fmon; mtmp; mtmp = mtmp2) {
202 			long            newhp;	/* tmoves may be very large */
203 
204 			mtmp2 = mtmp->nmon;
205 			if (strchr(genocided, mtmp->data->mlet)) {
206 				mondead(mtmp);
207 				continue;
208 			}
209 			if (mtmp->mtame && tmoves > 250) {
210 				mtmp->mtame = 0;
211 				mtmp->mpeaceful = 0;
212 			}
213 			newhp = mtmp->mhp +
214 				(strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20);
215 			if (newhp > mtmp->mhpmax)
216 				mtmp->mhp = mtmp->mhpmax;
217 			else
218 				mtmp->mhp = newhp;
219 		}
220 	}
221 
222 	setgd();
223 	gold = newgold();
224 	mread(fd, (char *) gold, sizeof(struct gold));
225 	while (gold->gx) {
226 		gold->ngold = fgold;
227 		fgold = gold;
228 		gold = newgold();
229 		mread(fd, (char *) gold, sizeof(struct gold));
230 	}
231 	free((char *) gold);
232 	trap = newtrap();
233 	mread(fd, (char *) trap, sizeof(struct trap));
234 	while (trap->tx) {
235 		trap->ntrap = ftrap;
236 		ftrap = trap;
237 		trap = newtrap();
238 		mread(fd, (char *) trap, sizeof(struct trap));
239 	}
240 	free((char *) trap);
241 	fobj = restobjchn(fd);
242 	billobjs = restobjchn(fd);
243 	rest_engravings(fd);
244 #ifndef QUEST
245 	mread(fd, (char *) rooms, sizeof(rooms));
246 	mread(fd, (char *) doors, sizeof(doors));
247 #endif	/* QUEST */
248 #ifndef NOWORM
249 	mread(fd, (char *) wsegs, sizeof(wsegs));
250 	for (tmp = 1; tmp < 32; tmp++)
251 		if (wsegs[tmp]) {
252 			wheads[tmp] = wsegs[tmp] = wtmp = newseg();
253 			while (1) {
254 				mread(fd, (char *) wtmp, sizeof(struct wseg));
255 				if (!wtmp->nseg)
256 					break;
257 				wheads[tmp]->nseg = wtmp = newseg();
258 				wheads[tmp] = wtmp;
259 			}
260 		}
261 	mread(fd, (char *) wgrowtime, sizeof(wgrowtime));
262 #endif	/* NOWORM */
263 }
264 
265 void
266 mread(fd, buf, len)
267 	int fd;
268 	char           *buf;
269 	unsigned        len;
270 {
271 	int             rlen;
272 
273 	rlen = read(fd, buf, (int) len);
274 	if (rlen != len) {
275 		pline("Read %d instead of %u bytes.\n", rlen, len);
276 		if (restoring) {
277 			(void) unlink(SAVEF);
278 			error("Error restoring old game.");
279 		}
280 		panic("Error reading level file.");
281 	}
282 }
283 
284 void
285 mklev()
286 {
287 	if (getbones())
288 		return;
289 
290 	in_mklev = TRUE;
291 	makelevel();
292 	in_mklev = FALSE;
293 }
294