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