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