1 /* $NetBSD: hack.lev.c,v 1.10 2009/06/07 18:30:39 dholland Exp $ */ 2 3 /* 4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5 * Amsterdam 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 11 * 12 * - Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * - Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * - Neither the name of the Stichting Centrum voor Wiskunde en 20 * Informatica, nor the names of its contributors may be used to endorse or 21 * promote products derived from this software without specific prior 22 * written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> 39 * All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #include <sys/cdefs.h> 65 #ifndef lint 66 __RCSID("$NetBSD: hack.lev.c,v 1.10 2009/06/07 18:30:39 dholland Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include <unistd.h> 71 #include "hack.h" 72 #include "extern.h" 73 #include "def.mkroom.h" 74 75 #ifndef NOWORM 76 #include "def.wseg.h" 77 #endif /* NOWORM */ 78 79 boolean level_exists[MAXLEVEL + 1]; 80 81 void 82 savelev(int fd, xchar lev) 83 { 84 #ifndef NOWORM 85 struct wseg *wtmp, *wtmp2; 86 int tmp; 87 #endif /* NOWORM */ 88 89 if (fd < 0) 90 panic("Save on bad file!"); /* impossible */ 91 if (lev >= 0 && lev <= MAXLEVEL) 92 level_exists[lev] = TRUE; 93 94 bwrite(fd, (char *) &hackpid, sizeof(hackpid)); 95 bwrite(fd, (char *) &lev, sizeof(lev)); 96 bwrite(fd, (char *) levl, sizeof(levl)); 97 bwrite(fd, (char *) &moves, sizeof(long)); 98 bwrite(fd, (char *) &xupstair, sizeof(xupstair)); 99 bwrite(fd, (char *) &yupstair, sizeof(yupstair)); 100 bwrite(fd, (char *) &xdnstair, sizeof(xdnstair)); 101 bwrite(fd, (char *) &ydnstair, sizeof(ydnstair)); 102 savemonchn(fd, fmon); 103 savegoldchn(fd, fgold); 104 savetrapchn(fd, ftrap); 105 saveobjchn(fd, fobj); 106 saveobjchn(fd, billobjs); 107 billobjs = 0; 108 save_engravings(fd); 109 #ifndef QUEST 110 bwrite(fd, (char *) rooms, sizeof(rooms)); 111 bwrite(fd, (char *) doors, sizeof(doors)); 112 #endif /* QUEST */ 113 fgold = 0; 114 ftrap = 0; 115 fmon = 0; 116 fobj = 0; 117 #ifndef NOWORM 118 bwrite(fd, (char *) wsegs, sizeof(wsegs)); 119 for (tmp = 1; tmp < 32; tmp++) { 120 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { 121 wtmp2 = wtmp->nseg; 122 bwrite(fd, (char *) wtmp, sizeof(struct wseg)); 123 } 124 wsegs[tmp] = 0; 125 } 126 bwrite(fd, (char *) wgrowtime, sizeof(wgrowtime)); 127 #endif /* NOWORM */ 128 } 129 130 void 131 bwrite(int fd, const void *loc, size_t num) 132 { 133 /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ 134 if ((size_t)write(fd, loc, num) != num) 135 panic("cannot write %zu bytes to file #%d", num, fd); 136 } 137 138 void 139 saveobjchn(int fd, struct obj *otmp) 140 { 141 struct obj *otmp2; 142 unsigned xl; 143 int minusone = -1; 144 145 while (otmp) { 146 otmp2 = otmp->nobj; 147 xl = otmp->onamelth; 148 bwrite(fd, (char *) &xl, sizeof(int)); 149 bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); 150 free((char *) otmp); 151 otmp = otmp2; 152 } 153 bwrite(fd, (char *) &minusone, sizeof(int)); 154 } 155 156 void 157 savemonchn(int fd, struct monst *mtmp) 158 { 159 struct monst *mtmp2; 160 unsigned xl; 161 int minusone = -1; 162 const struct permonst *monbegin = &mons[0]; 163 164 bwrite(fd, &monbegin, sizeof(monbegin)); 165 166 while (mtmp) { 167 mtmp2 = mtmp->nmon; 168 xl = mtmp->mxlth + mtmp->mnamelth; 169 bwrite(fd, (char *) &xl, sizeof(int)); 170 bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); 171 if (mtmp->minvent) 172 saveobjchn(fd, mtmp->minvent); 173 free((char *) mtmp); 174 mtmp = mtmp2; 175 } 176 bwrite(fd, (char *) &minusone, sizeof(int)); 177 } 178 179 void 180 savegoldchn(int fd, struct gold *gold) 181 { 182 struct gold *gold2; 183 while (gold) { 184 gold2 = gold->ngold; 185 bwrite(fd, (char *) gold, sizeof(struct gold)); 186 free((char *) gold); 187 gold = gold2; 188 } 189 bwrite(fd, nul, sizeof(struct gold)); 190 } 191 192 void 193 savetrapchn(int fd, struct trap *trap) 194 { 195 struct trap *trap2; 196 while (trap) { 197 trap2 = trap->ntrap; 198 bwrite(fd, (char *) trap, sizeof(struct trap)); 199 free((char *) trap); 200 trap = trap2; 201 } 202 bwrite(fd, nul, sizeof(struct trap)); 203 } 204 205 void 206 getlev(int fd, int pid, xchar lev) 207 { 208 struct gold *gold; 209 struct trap *trap; 210 #ifndef NOWORM 211 struct wseg *wtmp; 212 #endif /* NOWORM */ 213 int tmp; 214 long omoves; 215 int hpid; 216 xchar dlvl; 217 218 /* First some sanity checks */ 219 mread(fd, (char *) &hpid, sizeof(hpid)); 220 mread(fd, (char *) &dlvl, sizeof(dlvl)); 221 if ((pid && pid != hpid) || (lev && dlvl != lev)) { 222 pline("Strange, this map is not as I remember it."); 223 pline("Somebody is trying some trickery here ..."); 224 pline("This game is void ..."); 225 done("tricked"); 226 } 227 fgold = 0; 228 ftrap = 0; 229 mread(fd, (char *) levl, sizeof(levl)); 230 mread(fd, (char *) &omoves, sizeof(omoves)); 231 mread(fd, (char *) &xupstair, sizeof(xupstair)); 232 mread(fd, (char *) &yupstair, sizeof(yupstair)); 233 mread(fd, (char *) &xdnstair, sizeof(xdnstair)); 234 mread(fd, (char *) &ydnstair, sizeof(ydnstair)); 235 236 fmon = restmonchn(fd); 237 238 /* regenerate animals while on another level */ 239 { 240 long tmoves = (moves > omoves) ? moves - omoves : 0; 241 struct monst *mtmp, *mtmp2; 242 243 for (mtmp = fmon; mtmp; mtmp = mtmp2) { 244 long newhp; /* tmoves may be very large */ 245 246 mtmp2 = mtmp->nmon; 247 if (strchr(genocided, mtmp->data->mlet)) { 248 mondead(mtmp); 249 continue; 250 } 251 if (mtmp->mtame && tmoves > 250) { 252 mtmp->mtame = 0; 253 mtmp->mpeaceful = 0; 254 } 255 newhp = mtmp->mhp + 256 (strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20); 257 if (newhp > mtmp->mhpmax) 258 mtmp->mhp = mtmp->mhpmax; 259 else 260 mtmp->mhp = newhp; 261 } 262 } 263 264 setgd(); 265 gold = newgold(); 266 mread(fd, (char *) gold, sizeof(struct gold)); 267 while (gold->gx) { 268 gold->ngold = fgold; 269 fgold = gold; 270 gold = newgold(); 271 mread(fd, (char *) gold, sizeof(struct gold)); 272 } 273 free((char *) gold); 274 trap = newtrap(); 275 mread(fd, (char *) trap, sizeof(struct trap)); 276 while (trap->tx) { 277 trap->ntrap = ftrap; 278 ftrap = trap; 279 trap = newtrap(); 280 mread(fd, (char *) trap, sizeof(struct trap)); 281 } 282 free((char *) trap); 283 fobj = restobjchn(fd); 284 billobjs = restobjchn(fd); 285 rest_engravings(fd); 286 #ifndef QUEST 287 mread(fd, (char *) rooms, sizeof(rooms)); 288 mread(fd, (char *) doors, sizeof(doors)); 289 #endif /* QUEST */ 290 #ifndef NOWORM 291 mread(fd, (char *) wsegs, sizeof(wsegs)); 292 for (tmp = 1; tmp < 32; tmp++) 293 if (wsegs[tmp]) { 294 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 295 while (1) { 296 mread(fd, (char *) wtmp, sizeof(struct wseg)); 297 if (!wtmp->nseg) 298 break; 299 wheads[tmp]->nseg = wtmp = newseg(); 300 wheads[tmp] = wtmp; 301 } 302 } 303 mread(fd, (char *) wgrowtime, sizeof(wgrowtime)); 304 #endif /* NOWORM */ 305 } 306 307 void 308 mread(int fd, char *buf, unsigned len) 309 { 310 int rlen; 311 312 rlen = read(fd, buf, len); 313 if (rlen < 0 || (size_t)rlen != len) { 314 pline("Read %d instead of %u bytes.\n", rlen, len); 315 if (restoring) { 316 (void) unlink(SAVEF); 317 error("Error restoring old game."); 318 } 319 panic("Error reading level file."); 320 } 321 } 322 323 void 324 mklev(void) 325 { 326 if (getbones()) 327 return; 328 329 in_mklev = TRUE; 330 makelevel(); 331 in_mklev = FALSE; 332 } 333