xref: /dragonfly/games/hack/hack.lev.c (revision 0fe46dc6)
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 
5 #include "hack.h"
6 extern struct obj *billobjs;
7 extern char SAVEF[];
8 extern char nul[];
9 
10 #ifndef NOWORM
11 extern struct wseg *wsegs[32], *wheads[32];
12 extern long wgrowtime[32];
13 #endif /* NOWORM */
14 
15 boolean level_exists[MAXLEVEL+1];
16 
17 static void savegoldchn(int, struct gold *);
18 static void savetrapchn(int, struct trap *);
19 
20 void
21 savelev(int fd, xchar lev)
22 {
23 #ifndef NOWORM
24 	struct wseg *wtmp, *wtmp2;
25 	int tmp;
26 #endif /* NOWORM */
27 
28 	if (fd < 0)
29 		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 = NULL;
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] = NULL;
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(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)
111 			saveobjchn(fd, mtmp->minvent);
112 		free(mtmp);
113 		mtmp = mtmp2;
114 	}
115 	bwrite(fd, (char *)&minusone, sizeof(int));
116 }
117 
118 static void
119 savegoldchn(int fd, struct gold *gold)
120 {
121 	struct gold *gold2;
122 
123 	while (gold) {
124 		gold2 = gold->ngold;
125 		bwrite(fd, (char *)gold, sizeof(struct gold));
126 		free(gold);
127 		gold = gold2;
128 	}
129 	bwrite(fd, nul, sizeof(struct gold));
130 }
131 
132 static void
133 savetrapchn(int fd, struct trap *trap)
134 {
135 	struct trap *trap2;
136 
137 	while (trap) {
138 		trap2 = trap->ntrap;
139 		bwrite(fd, (char *)trap, sizeof(struct trap));
140 		free(trap);
141 		trap = trap2;
142 	}
143 	bwrite(fd, nul, sizeof(struct trap));
144 }
145 
146 void
147 getlev(int fd, int pid, xchar lev)
148 {
149 	struct gold *gold;
150 	struct trap *trap;
151 #ifndef NOWORM
152 	struct wseg *wtmp;
153 #endif /* NOWORM */
154 	int tmp;
155 	long omoves;
156 	int hpid;
157 	xchar dlvl;
158 
159 	/* First some sanity checks */
160 	mread(fd, (char *)&hpid, sizeof(hpid));
161 	mread(fd, (char *)&dlvl, sizeof(dlvl));
162 	if ((pid && pid != hpid) || (lev && dlvl != lev)) {
163 		pline("Strange, this map is not as I remember it.");
164 		pline("Somebody is trying some trickery here ...");
165 		pline("This game is void ...");
166 		done("tricked");
167 	}
168 
169 	fgold = 0;
170 	ftrap = 0;
171 	mread(fd, (char *)levl, sizeof(levl));
172 	mread(fd, (char *)&omoves, sizeof(omoves));
173 	mread(fd, (char *)&xupstair, sizeof(xupstair));
174 	mread(fd, (char *)&yupstair, sizeof(yupstair));
175 	mread(fd, (char *)&xdnstair, sizeof(xdnstair));
176 	mread(fd, (char *)&ydnstair, sizeof(ydnstair));
177 
178 	fmon = restmonchn(fd);
179 
180 	/* regenerate animals while on another level */
181 	{
182 		long tmoves = (moves > omoves) ? moves - omoves : 0;
183 		struct monst *mtmp, *mtmp2;
184 
185 		for (mtmp = fmon; mtmp; mtmp = mtmp2) {
186 			long newhp;           /* tmoves may be very large */
187 
188 			mtmp2 = mtmp->nmon;
189 			if (strchr(genocided, mtmp->data->mlet)) {
190 				mondead(mtmp);
191 				continue;
192 			}
193 
194 			if (mtmp->mtame && tmoves > 250) {
195 				mtmp->mtame = 0;
196 				mtmp->mpeaceful = 0;
197 			}
198 
199 			newhp = mtmp->mhp +
200 			    (strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20);
201 			if (newhp > mtmp->mhpmax)
202 				mtmp->mhp = mtmp->mhpmax;
203 			else
204 				mtmp->mhp = newhp;
205 		}
206 	}
207 
208 	setgd();
209 	gold = newgold();
210 	mread(fd, (char *)gold, sizeof(struct gold));
211 	while (gold->gx) {
212 		gold->ngold = fgold;
213 		fgold = gold;
214 		gold = newgold();
215 		mread(fd, (char *)gold, sizeof(struct gold));
216 	}
217 	free(gold);
218 	trap = newtrap();
219 	mread(fd, (char *)trap, sizeof(struct trap));
220 	while (trap->tx) {
221 		trap->ntrap = ftrap;
222 		ftrap = trap;
223 		trap = newtrap();
224 		mread(fd, (char *)trap, sizeof(struct trap));
225 	}
226 	free(trap);
227 	fobj = restobjchn(fd);
228 	billobjs = restobjchn(fd);
229 	rest_engravings(fd);
230 #ifndef QUEST
231 	mread(fd, (char *)rooms, sizeof(rooms));
232 	mread(fd, (char *)doors, sizeof(doors));
233 #endif /* QUEST */
234 #ifndef NOWORM
235 	mread(fd, (char *)wsegs, sizeof(wsegs));
236 	for (tmp = 1; tmp < 32; tmp++)
237 		if (wsegs[tmp]) {
238 			wheads[tmp] = wsegs[tmp] = wtmp = newseg();
239 			for (;;) {
240 				mread(fd, (char *)wtmp, sizeof(struct wseg));
241 				if (!wtmp->nseg)
242 					break;
243 				wheads[tmp]->nseg = wtmp = newseg();
244 				wheads[tmp] = wtmp;
245 			}
246 		}
247 	mread(fd, (char *)wgrowtime, sizeof(wgrowtime));
248 #endif /* NOWORM */
249 }
250 
251 void
252 mread(int fd, char *buf, unsigned int len)
253 {
254 	int rlen;
255 
256 	rlen = read(fd, buf, (int)len);
257 	if (rlen != (int)len) {
258 		pline("Read %d instead of %u bytes.\n", rlen, len);
259 		if (restoring) {
260 			unlink(SAVEF);
261 			error("Error restoring old game.");
262 		}
263 		panic("Error reading level file.");
264 	}
265 }
266 
267 void
268 mklev(void)
269 {
270 	if (getbones())
271 		return;
272 
273 	in_mklev = TRUE;
274 	makelevel();
275 	in_mklev = FALSE;
276 }
277