1 /* $OpenBSD: hack.lev.c,v 1.7 2009/10/27 23:59:25 deraadt 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 <stdio.h> 65 #include <stdlib.h> 66 #include <unistd.h> 67 #include "hack.h" 68 69 extern struct obj *billobjs; 70 extern char SAVEF[]; 71 extern int hackpid; 72 extern xchar dlevel; 73 extern char nul[]; 74 75 #ifndef NOWORM 76 extern struct wseg *wsegs[32], *wheads[32]; 77 extern long wgrowtime[32]; 78 #endif /* NOWORM */ 79 80 boolean level_exists[MAXLEVEL+1]; 81 82 void 83 savelev(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,(char *) &hackpid,sizeof(hackpid)); 96 bwrite(fd,(char *) &lev,sizeof(lev)); 97 bwrite(fd,(char *) levl,sizeof(levl)); 98 bwrite(fd,(char *) &moves,sizeof(long)); 99 bwrite(fd,(char *) &xupstair,sizeof(xupstair)); 100 bwrite(fd,(char *) &yupstair,sizeof(yupstair)); 101 bwrite(fd,(char *) &xdnstair,sizeof(xdnstair)); 102 bwrite(fd,(char *) &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,(char *) rooms,sizeof(rooms)); 112 bwrite(fd,(char *) doors,sizeof(doors)); 113 #endif /* QUEST */ 114 fgold = 0; 115 ftrap = 0; 116 fmon = 0; 117 fobj = 0; 118 #ifndef NOWORM 119 bwrite(fd,(char *) 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,(char *) wtmp,sizeof(struct wseg)); 124 } 125 wsegs[tmp] = 0; 126 } 127 bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime)); 128 #endif /* NOWORM */ 129 } 130 131 void 132 bwrite(int fd, char *loc, unsigned int num) 133 { 134 /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ 135 if(write(fd, loc, (int) num) != num) 136 panic("cannot write %u bytes to file #%d", num, fd); 137 } 138 139 void 140 saveobjchn(int fd, struct obj *otmp) 141 { 142 struct obj *otmp2; 143 unsigned xl; 144 int minusone = -1; 145 146 while(otmp) { 147 otmp2 = otmp->nobj; 148 xl = otmp->onamelth; 149 bwrite(fd, (char *) &xl, sizeof(int)); 150 bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); 151 free((char *) otmp); 152 otmp = otmp2; 153 } 154 bwrite(fd, (char *) &minusone, sizeof(int)); 155 } 156 157 void 158 savemonchn(int fd, struct monst *mtmp) 159 { 160 struct monst *mtmp2; 161 unsigned xl; 162 int minusone = -1; 163 struct permonst *monbegin = &mons[0]; 164 165 bwrite(fd, (char *) &monbegin, sizeof(monbegin)); 166 167 while(mtmp) { 168 mtmp2 = mtmp->nmon; 169 xl = mtmp->mxlth + mtmp->mnamelth; 170 bwrite(fd, (char *) &xl, sizeof(int)); 171 bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); 172 if(mtmp->minvent) 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 228 fgold = 0; 229 ftrap = 0; 230 mread(fd, (char *) levl, sizeof(levl)); 231 mread(fd, (char *)&omoves, sizeof(omoves)); 232 mread(fd, (char *)&xupstair, sizeof(xupstair)); 233 mread(fd, (char *)&yupstair, sizeof(yupstair)); 234 mread(fd, (char *)&xdnstair, sizeof(xdnstair)); 235 mread(fd, (char *)&ydnstair, sizeof(ydnstair)); 236 237 fmon = restmonchn(fd); 238 239 /* regenerate animals while on another level */ 240 { long tmoves = (moves > omoves) ? moves-omoves : 0; 241 struct monst *mtmp, *mtmp2; 242 extern char genocided[]; 243 244 for(mtmp = fmon; mtmp; mtmp = mtmp2) { 245 long newhp; /* tmoves may be very large */ 246 247 mtmp2 = mtmp->nmon; 248 if(strchr(genocided, mtmp->data->mlet)) { 249 mondead(mtmp); 250 continue; 251 } 252 253 if(mtmp->mtame && tmoves > 250) { 254 mtmp->mtame = 0; 255 mtmp->mpeaceful = 0; 256 } 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, (char *)gold, sizeof(struct gold)); 270 while(gold->gx) { 271 gold->ngold = fgold; 272 fgold = gold; 273 gold = newgold(); 274 mread(fd, (char *)gold, sizeof(struct gold)); 275 } 276 free((char *) gold); 277 trap = newtrap(); 278 mread(fd, (char *)trap, sizeof(struct trap)); 279 while(trap->tx) { 280 trap->ntrap = ftrap; 281 ftrap = trap; 282 trap = newtrap(); 283 mread(fd, (char *)trap, sizeof(struct trap)); 284 } 285 free((char *) trap); 286 fobj = restobjchn(fd); 287 billobjs = restobjchn(fd); 288 rest_engravings(fd); 289 #ifndef QUEST 290 mread(fd, (char *)rooms, sizeof(rooms)); 291 mread(fd, (char *)doors, sizeof(doors)); 292 #endif /* QUEST */ 293 #ifndef NOWORM 294 mread(fd, (char *)wsegs, sizeof(wsegs)); 295 for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ 296 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 297 while(1) { 298 mread(fd, (char *)wtmp, sizeof(struct wseg)); 299 if(!wtmp->nseg) break; 300 wheads[tmp]->nseg = wtmp = newseg(); 301 wheads[tmp] = wtmp; 302 } 303 } 304 mread(fd, (char *)wgrowtime, sizeof(wgrowtime)); 305 #endif /* NOWORM */ 306 } 307 308 void 309 mread(int fd, char *buf, unsigned len) 310 { 311 int rlen; 312 extern boolean restoring; 313 314 rlen = read(fd, buf, (int) len); 315 if(rlen != len){ 316 pline("Read %d instead of %u bytes.\n", rlen, len); 317 if(restoring) { 318 (void) unlink(SAVEF); 319 error("Error restoring old game."); 320 } 321 panic("Error reading level file."); 322 } 323 } 324 325 void 326 mklev() 327 { 328 extern boolean in_mklev; 329 330 if(getbones()) return; 331 332 in_mklev = TRUE; 333 makelevel(); 334 in_mklev = FALSE; 335 } 336