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