1/* $OpenBSD: hack.lev.c,v 1.10 2016/01/09 18:33:15 mestre 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 67#include "hack.h" 68 69extern struct obj *billobjs; 70extern char SAVEF[]; 71extern int hackpid; 72extern xchar dlevel; 73extern char nul[]; 74 75#ifndef NOWORM 76extern struct wseg *wsegs[32], *wheads[32]; 77extern long wgrowtime[32]; 78#endif /* NOWORM */ 79 80boolean level_exists[MAXLEVEL+1]; 81 82void 83savelev(int fd, xchar lev) 84{ 85#ifndef NOWORM 86 struct wseg *wtmp, *wtmp2; 87 int tmp; 88#endif /* NOWORM */ 89 90 if (fd < 0) 91 panic("Save on bad file!"); /* impossible */ 92 if (lev >= 0 && lev <= MAXLEVEL) 93 level_exists[(int)lev] = TRUE; 94 95 bwrite(fd, &hackpid,sizeof(hackpid)); 96 bwrite(fd, &lev,sizeof(lev)); 97 bwrite(fd, levl,sizeof(levl)); 98 bwrite(fd, &moves,sizeof(long)); 99 bwrite(fd, &xupstair,sizeof(xupstair)); 100 bwrite(fd, &yupstair,sizeof(yupstair)); 101 bwrite(fd, &xdnstair,sizeof(xdnstair)); 102 bwrite(fd, &ydnstair,sizeof(ydnstair)); 103 savemonchn(fd, fmon); 104 savegoldchn(fd, fgold); 105 savetrapchn(fd, ftrap); 106 saveobjchn(fd, fobj); 107 saveobjchn(fd, billobjs); 108 billobjs = 0; 109 save_engravings(fd); 110#ifndef QUEST 111 bwrite(fd, rooms,sizeof(rooms)); 112 bwrite(fd, doors,sizeof(doors)); 113#endif /* QUEST */ 114 fgold = 0; 115 ftrap = 0; 116 fmon = 0; 117 fobj = 0; 118#ifndef NOWORM 119 bwrite(fd, wsegs,sizeof(wsegs)); 120 for(tmp=1; tmp<32; tmp++){ 121 for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){ 122 wtmp2 = wtmp->nseg; 123 bwrite(fd, wtmp,sizeof(struct wseg)); 124 } 125 wsegs[tmp] = 0; 126 } 127 bwrite(fd, wgrowtime,sizeof(wgrowtime)); 128#endif /* NOWORM */ 129} 130 131void 132bwrite(int fd, const void *loc, ssize_t num) 133{ 134 if(write(fd, loc, num) != num) 135 panic("cannot write %zd bytes to file #%d", num, fd); 136} 137 138void 139saveobjchn(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, &xl, sizeof(int)); 149 bwrite(fd, otmp, xl + sizeof(struct obj)); 150 free(otmp); 151 otmp = otmp2; 152 } 153 bwrite(fd, &minusone, sizeof(int)); 154} 155 156void 157savemonchn(int fd, struct monst *mtmp) 158{ 159 struct monst *mtmp2; 160 unsigned xl; 161 int minusone = -1; 162 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, &xl, sizeof(int)); 170 bwrite(fd, mtmp, xl + sizeof(struct monst)); 171 if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); 172 free(mtmp); 173 mtmp = mtmp2; 174 } 175 bwrite(fd, &minusone, sizeof(int)); 176} 177 178void 179savegoldchn(int fd, struct gold *gold) 180{ 181 struct gold *gold2; 182 while(gold) { 183 gold2 = gold->ngold; 184 bwrite(fd, gold, sizeof(struct gold)); 185 free(gold); 186 gold = gold2; 187 } 188 bwrite(fd, nul, sizeof(struct gold)); 189} 190 191void 192savetrapchn(int fd, struct trap *trap) 193{ 194 struct trap *trap2; 195 while(trap) { 196 trap2 = trap->ntrap; 197 bwrite(fd, trap, sizeof(struct trap)); 198 free(trap); 199 trap = trap2; 200 } 201 bwrite(fd, nul, sizeof(struct trap)); 202} 203 204void 205getlev(int fd, int pid, xchar lev) 206{ 207 struct gold *gold; 208 struct trap *trap; 209#ifndef NOWORM 210 struct wseg *wtmp; 211#endif /* NOWORM */ 212 int tmp; 213 long omoves; 214 int hpid; 215 xchar dlvl; 216 217 /* First some sanity checks */ 218 mread(fd, (char *) &hpid, sizeof(hpid)); 219 mread(fd, (char *) &dlvl, sizeof(dlvl)); 220 if((pid && pid != hpid) || (lev && dlvl != lev)) { 221 pline("Strange, this map is not as I remember it."); 222 pline("Somebody is trying some trickery here ..."); 223 pline("This game is void ..."); 224 done("tricked"); 225 } 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 { long tmoves = (moves > omoves) ? moves-omoves : 0; 240 struct monst *mtmp, *mtmp2; 241 extern char genocided[]; 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 252 if(mtmp->mtame && tmoves > 250) { 253 mtmp->mtame = 0; 254 mtmp->mpeaceful = 0; 255 } 256 257 newhp = mtmp->mhp + 258 (strchr(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20); 259 if(newhp > mtmp->mhpmax) 260 mtmp->mhp = mtmp->mhpmax; 261 else 262 mtmp->mhp = newhp; 263 } 264 } 265 266 setgd(); 267 gold = newgold(); 268 mread(fd, (char *)gold, sizeof(struct gold)); 269 while(gold->gx) { 270 gold->ngold = fgold; 271 fgold = gold; 272 gold = newgold(); 273 mread(fd, (char *)gold, sizeof(struct gold)); 274 } 275 free(gold); 276 trap = newtrap(); 277 mread(fd, (char *)trap, sizeof(struct trap)); 278 while(trap->tx) { 279 trap->ntrap = ftrap; 280 ftrap = trap; 281 trap = newtrap(); 282 mread(fd, (char *)trap, sizeof(struct trap)); 283 } 284 free(trap); 285 fobj = restobjchn(fd); 286 billobjs = restobjchn(fd); 287 rest_engravings(fd); 288#ifndef QUEST 289 mread(fd, (char *)rooms, sizeof(rooms)); 290 mread(fd, (char *)doors, sizeof(doors)); 291#endif /* QUEST */ 292#ifndef NOWORM 293 mread(fd, (char *)wsegs, sizeof(wsegs)); 294 for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ 295 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 296 while(1) { 297 mread(fd, (char *)wtmp, sizeof(struct wseg)); 298 if(!wtmp->nseg) 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 307void 308mread(int fd, char *buf, unsigned len) 309{ 310 int rlen; 311 extern boolean restoring; 312 313 rlen = read(fd, buf, (int) len); 314 if(rlen != len){ 315 pline("Read %d instead of %u bytes.\n", rlen, len); 316 if(restoring) { 317 (void) unlink(SAVEF); 318 error("Error restoring old game."); 319 } 320 panic("Error reading level file."); 321 } 322} 323 324void 325mklev(void) 326{ 327 extern boolean in_mklev; 328 329 if(getbones()) return; 330 331 in_mklev = TRUE; 332 makelevel(); 333 in_mklev = FALSE; 334} 335