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