1 /* $NetBSD: hack.lev.c,v 1.7 2008/01/28 06:55:41 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.7 2008/01/28 06:55:41 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(fd, lev) 83 int fd; 84 xchar lev; 85 { 86 #ifndef NOWORM 87 struct wseg *wtmp, *wtmp2; 88 int tmp; 89 #endif /* NOWORM */ 90 91 if (fd < 0) 92 panic("Save on bad file!"); /* impossible */ 93 if (lev >= 0 && lev <= MAXLEVEL) 94 level_exists[lev] = TRUE; 95 96 bwrite(fd, (char *) &hackpid, sizeof(hackpid)); 97 bwrite(fd, (char *) &lev, sizeof(lev)); 98 bwrite(fd, (char *) levl, sizeof(levl)); 99 bwrite(fd, (char *) &moves, sizeof(long)); 100 bwrite(fd, (char *) &xupstair, sizeof(xupstair)); 101 bwrite(fd, (char *) &yupstair, sizeof(yupstair)); 102 bwrite(fd, (char *) &xdnstair, sizeof(xdnstair)); 103 bwrite(fd, (char *) &ydnstair, sizeof(ydnstair)); 104 savemonchn(fd, fmon); 105 savegoldchn(fd, fgold); 106 savetrapchn(fd, ftrap); 107 saveobjchn(fd, fobj); 108 saveobjchn(fd, billobjs); 109 billobjs = 0; 110 save_engravings(fd); 111 #ifndef QUEST 112 bwrite(fd, (char *) rooms, sizeof(rooms)); 113 bwrite(fd, (char *) doors, sizeof(doors)); 114 #endif /* QUEST */ 115 fgold = 0; 116 ftrap = 0; 117 fmon = 0; 118 fobj = 0; 119 #ifndef NOWORM 120 bwrite(fd, (char *) wsegs, sizeof(wsegs)); 121 for (tmp = 1; tmp < 32; tmp++) { 122 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { 123 wtmp2 = wtmp->nseg; 124 bwrite(fd, (char *) wtmp, sizeof(struct wseg)); 125 } 126 wsegs[tmp] = 0; 127 } 128 bwrite(fd, (char *) wgrowtime, sizeof(wgrowtime)); 129 #endif /* NOWORM */ 130 } 131 132 void 133 bwrite(fd, loc, num) 134 int fd; 135 const void *loc; 136 unsigned num; 137 { 138 /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ 139 if (write(fd, loc, (int) num) != num) 140 panic("cannot write %u bytes to file #%d", num, fd); 141 } 142 143 void 144 saveobjchn(fd, otmp) 145 int fd; 146 struct obj *otmp; 147 { 148 struct obj *otmp2; 149 unsigned xl; 150 int minusone = -1; 151 152 while (otmp) { 153 otmp2 = otmp->nobj; 154 xl = otmp->onamelth; 155 bwrite(fd, (char *) &xl, sizeof(int)); 156 bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); 157 free((char *) otmp); 158 otmp = otmp2; 159 } 160 bwrite(fd, (char *) &minusone, sizeof(int)); 161 } 162 163 void 164 savemonchn(fd, mtmp) 165 int fd; 166 struct monst *mtmp; 167 { 168 struct monst *mtmp2; 169 unsigned xl; 170 int minusone = -1; 171 const struct permonst *monbegin = &mons[0]; 172 173 bwrite(fd, &monbegin, sizeof(monbegin)); 174 175 while (mtmp) { 176 mtmp2 = mtmp->nmon; 177 xl = mtmp->mxlth + mtmp->mnamelth; 178 bwrite(fd, (char *) &xl, sizeof(int)); 179 bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); 180 if (mtmp->minvent) 181 saveobjchn(fd, mtmp->minvent); 182 free((char *) mtmp); 183 mtmp = mtmp2; 184 } 185 bwrite(fd, (char *) &minusone, sizeof(int)); 186 } 187 188 void 189 savegoldchn(fd, gold) 190 int fd; 191 struct gold *gold; 192 { 193 struct gold *gold2; 194 while (gold) { 195 gold2 = gold->ngold; 196 bwrite(fd, (char *) gold, sizeof(struct gold)); 197 free((char *) gold); 198 gold = gold2; 199 } 200 bwrite(fd, nul, sizeof(struct gold)); 201 } 202 203 void 204 savetrapchn(fd, trap) 205 int fd; 206 struct trap *trap; 207 { 208 struct trap *trap2; 209 while (trap) { 210 trap2 = trap->ntrap; 211 bwrite(fd, (char *) trap, sizeof(struct trap)); 212 free((char *) trap); 213 trap = trap2; 214 } 215 bwrite(fd, nul, sizeof(struct trap)); 216 } 217 218 void 219 getlev(fd, pid, lev) 220 int fd, pid; 221 xchar lev; 222 { 223 struct gold *gold; 224 struct trap *trap; 225 #ifndef NOWORM 226 struct wseg *wtmp; 227 #endif /* NOWORM */ 228 int tmp; 229 long omoves; 230 int hpid; 231 xchar dlvl; 232 233 /* First some sanity checks */ 234 mread(fd, (char *) &hpid, sizeof(hpid)); 235 mread(fd, (char *) &dlvl, sizeof(dlvl)); 236 if ((pid && pid != hpid) || (lev && dlvl != lev)) { 237 pline("Strange, this map is not as I remember it."); 238 pline("Somebody is trying some trickery here ..."); 239 pline("This game is void ..."); 240 done("tricked"); 241 } 242 fgold = 0; 243 ftrap = 0; 244 mread(fd, (char *) levl, sizeof(levl)); 245 mread(fd, (char *) &omoves, sizeof(omoves)); 246 mread(fd, (char *) &xupstair, sizeof(xupstair)); 247 mread(fd, (char *) &yupstair, sizeof(yupstair)); 248 mread(fd, (char *) &xdnstair, sizeof(xdnstair)); 249 mread(fd, (char *) &ydnstair, sizeof(ydnstair)); 250 251 fmon = restmonchn(fd); 252 253 /* regenerate animals while on another level */ 254 { 255 long tmoves = (moves > omoves) ? moves - omoves : 0; 256 struct monst *mtmp, *mtmp2; 257 258 for (mtmp = fmon; mtmp; mtmp = mtmp2) { 259 long newhp; /* tmoves may be very large */ 260 261 mtmp2 = mtmp->nmon; 262 if (strchr(genocided, mtmp->data->mlet)) { 263 mondead(mtmp); 264 continue; 265 } 266 if (mtmp->mtame && tmoves > 250) { 267 mtmp->mtame = 0; 268 mtmp->mpeaceful = 0; 269 } 270 newhp = mtmp->mhp + 271 (strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves / 20); 272 if (newhp > mtmp->mhpmax) 273 mtmp->mhp = mtmp->mhpmax; 274 else 275 mtmp->mhp = newhp; 276 } 277 } 278 279 setgd(); 280 gold = newgold(); 281 mread(fd, (char *) gold, sizeof(struct gold)); 282 while (gold->gx) { 283 gold->ngold = fgold; 284 fgold = gold; 285 gold = newgold(); 286 mread(fd, (char *) gold, sizeof(struct gold)); 287 } 288 free((char *) gold); 289 trap = newtrap(); 290 mread(fd, (char *) trap, sizeof(struct trap)); 291 while (trap->tx) { 292 trap->ntrap = ftrap; 293 ftrap = trap; 294 trap = newtrap(); 295 mread(fd, (char *) trap, sizeof(struct trap)); 296 } 297 free((char *) trap); 298 fobj = restobjchn(fd); 299 billobjs = restobjchn(fd); 300 rest_engravings(fd); 301 #ifndef QUEST 302 mread(fd, (char *) rooms, sizeof(rooms)); 303 mread(fd, (char *) doors, sizeof(doors)); 304 #endif /* QUEST */ 305 #ifndef NOWORM 306 mread(fd, (char *) wsegs, sizeof(wsegs)); 307 for (tmp = 1; tmp < 32; tmp++) 308 if (wsegs[tmp]) { 309 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 310 while (1) { 311 mread(fd, (char *) wtmp, sizeof(struct wseg)); 312 if (!wtmp->nseg) 313 break; 314 wheads[tmp]->nseg = wtmp = newseg(); 315 wheads[tmp] = wtmp; 316 } 317 } 318 mread(fd, (char *) wgrowtime, sizeof(wgrowtime)); 319 #endif /* NOWORM */ 320 } 321 322 void 323 mread(fd, buf, len) 324 int fd; 325 char *buf; 326 unsigned len; 327 { 328 int rlen; 329 330 rlen = read(fd, buf, len); 331 if (rlen < 0 || (size_t)rlen != len) { 332 pline("Read %d instead of %u bytes.\n", rlen, len); 333 if (restoring) { 334 (void) unlink(SAVEF); 335 error("Error restoring old game."); 336 } 337 panic("Error reading level file."); 338 } 339 } 340 341 void 342 mklev() 343 { 344 if (getbones()) 345 return; 346 347 in_mklev = TRUE; 348 makelevel(); 349 in_mklev = FALSE; 350 } 351