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