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