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