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 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, &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 131 void 132 bwrite(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 138 void 139 saveobjchn(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 156 void 157 savemonchn(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 178 void 179 savegoldchn(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 191 void 192 savetrapchn(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 204 void 205 getlev(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 307 void 308 mread(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 324 void 325 mklev(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