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