Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / games / hack / hack.lev.c
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 }