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