lev.c (12779B)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* lev.c - version 1.0.3 */ 3 4 #include <stdio.h> 5 #include "hack.h" 6 #include "mkroom.h" 7 8 extern struct monst *restmonchn(); 9 extern struct obj *restobjchn(); 10 extern struct obj *billobjs; 11 extern char *itoa(); 12 extern int hackpid; 13 extern xchar dlevel; 14 extern char nul[], SAVEF[]; 15 16 #ifndef NOWORM 17 #include "wseg.h" 18 extern struct wseg *wsegs[32], *wheads[32]; 19 extern long wgrowtime[32]; 20 #endif /* NOWORM /**/ 21 22 #ifdef DGK 23 struct finfo fileinfo[MAXLEVEL+1]; 24 long bytes_counted; 25 int count_only; 26 #else 27 boolean level_exists[MAXLEVEL+1]; 28 #endif 29 30 #ifdef DGK 31 savelev(fd, lev, mode) 32 int fd, mode; 33 xchar lev; 34 { 35 if (mode & COUNT) { 36 count_only = TRUE; 37 bytes_counted = 0; 38 savelev0(fd, lev); 39 while (bytes_counted > freediskspace(levels)) 40 if (!swapout_oldest()) 41 return FALSE; 42 } 43 if (mode & WRITE) { 44 count_only = FALSE; 45 bytes_counted = 0; 46 savelev0(fd, lev); 47 } 48 fileinfo[lev].where = ACTIVE; 49 fileinfo[lev].time = moves; 50 fileinfo[lev].size = bytes_counted; 51 return TRUE; 52 } 53 54 savelev0(fd,lev) 55 #else 56 savelev(fd,lev) 57 #endif 58 int fd; 59 xchar lev; 60 { 61 #ifndef NOWORM 62 register struct wseg *wtmp, *wtmp2; 63 register tmp; 64 #endif /* NOWORM /**/ 65 66 if(fd < 0) panic("Save on bad file!"); /* impossible */ 67 #ifndef DGK 68 if(lev >= 0 && lev <= MAXLEVEL) 69 level_exists[lev] = TRUE; 70 #endif 71 72 #ifdef DGK 73 bwrite(fd, (char *) &vmajor, sizeof(vmajor)); 74 bwrite(fd, (char *) &vminor, sizeof(vminor)); 75 #endif 76 bwrite(fd,(char *) &hackpid,sizeof(hackpid)); 77 bwrite(fd,(char *) &lev,sizeof(lev)); 78 bwrite(fd,(char *) levl,sizeof(levl)); 79 #ifdef DGK 80 bwrite(fd, (char *) &symbol, sizeof(symbol)); 81 #endif 82 bwrite(fd,(char *) &moves,sizeof(long)); 83 bwrite(fd,(char *) &xupstair,sizeof(xupstair)); 84 bwrite(fd,(char *) &yupstair,sizeof(yupstair)); 85 bwrite(fd,(char *) &xdnstair,sizeof(xdnstair)); 86 bwrite(fd,(char *) &ydnstair,sizeof(ydnstair)); 87 savemonchn(fd, fmon); 88 savegoldchn(fd, fgold); 89 savetrapchn(fd, ftrap); 90 saveobjchn(fd, fobj); 91 saveobjchn(fd, billobjs); 92 save_engravings(fd); 93 bwrite(fd,(char *) rooms,sizeof(rooms)); 94 bwrite(fd,(char *) doors,sizeof(doors)); 95 #ifndef NOWORM 96 bwrite(fd,(char *) wsegs,sizeof(wsegs)); 97 for(tmp=1; tmp<32; tmp++){ 98 for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){ 99 wtmp2 = wtmp->nseg; 100 bwrite(fd,(char *) wtmp,sizeof(struct wseg)); 101 } 102 #ifdef DGK 103 if (!count_only) 104 #endif 105 wsegs[tmp] = 0; 106 } 107 bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime)); 108 #endif /* NOWORM /**/ 109 #ifdef DGK 110 if (count_only) 111 return; 112 #endif 113 billobjs = 0; 114 fgold = 0; 115 ftrap = 0; 116 fmon = 0; 117 fobj = 0; 118 } 119 120 bwrite(fd,loc,num) 121 register fd; 122 register char *loc; 123 register unsigned num; 124 { 125 126 bytes_counted += num; 127 #ifdef DGK 128 if (!count_only) 129 #endif 130 if (write(fd, loc, (unsigned) num) != num) 131 panic("bwrite: disk error"); 132 } 133 134 saveobjchn(fd,otmp) 135 register fd; 136 register struct obj *otmp; 137 { 138 register struct obj *otmp2; 139 unsigned xl; 140 int minusone = -1; 141 142 while(otmp) { 143 otmp2 = otmp->nobj; 144 xl = otmp->onamelth; 145 bwrite(fd, (char *) &xl, sizeof(int)); 146 bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); 147 #ifdef DGK 148 if (!count_only) 149 #endif 150 free((char *) otmp); 151 otmp = otmp2; 152 } 153 bwrite(fd, (char *) &minusone, sizeof(int)); 154 } 155 156 #ifdef MSDOS 157 /* We don't want to save any pointers in any files, so convert 158 * the pointers to indices before writing the monsters to disk -dgk 159 */ 160 savemonchn(fd,mtmp) 161 register fd; 162 register struct monst *mtmp; 163 { 164 register struct monst *mtmp2; 165 unsigned xl; 166 int minusone = -1; 167 struct permonst *permonstp; 168 int monsindex; 169 extern struct permonst li_dog, dog, la_dog, hell_hound, pm_guard; 170 extern struct permonst pm_eel; 171 172 while(mtmp) { 173 mtmp2 = mtmp->nmon; 174 xl = mtmp->mxlth + mtmp->mnamelth; 175 bwrite(fd, (char *) &xl, sizeof(int)); 176 /* store an index where the pointer used to be */ 177 permonstp = mtmp->data; 178 if (permonstp == &li_dog) 179 monsindex = INDEX_LITTLEDOG; 180 else if (permonstp == &dog) 181 monsindex = INDEX_DOG; 182 else if (permonstp == &la_dog) 183 monsindex = INDEX_LARGEDOG; 184 else if (permonstp == &hell_hound) 185 monsindex = INDEX_HELLHOUND; 186 else if (permonstp == &pm_guard) 187 monsindex = INDEX_GUARD; 188 else if (permonstp > &pm_eel || permonstp < &mons[0]) { 189 msmsg("Unsupported monster pointer in savemonchn\n"); 190 goto next; 191 } else 192 monsindex = permonstp - &mons[0]; 193 *((int *)&mtmp->data) = monsindex; 194 bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); 195 mtmp->data = permonstp; /* restore the pointer */ 196 if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); 197 #ifdef DGK 198 if (!count_only) 199 #endif 200 free((char *) mtmp); 201 next: 202 mtmp = mtmp2; 203 } 204 bwrite(fd, (char *) &minusone, sizeof(int)); 205 } 206 #else 207 208 savemonchn(fd,mtmp) 209 register fd; 210 register struct monst *mtmp; 211 { 212 register struct monst *mtmp2; 213 unsigned xl; 214 int minusone = -1; 215 struct permonst *monbegin = &mons[0]; 216 217 bwrite(fd, (char *) &monbegin, sizeof(monbegin)); 218 219 while(mtmp) { 220 mtmp2 = mtmp->nmon; 221 xl = mtmp->mxlth + mtmp->mnamelth; 222 bwrite(fd, (char *) &xl, sizeof(int)); 223 bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); 224 if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); 225 free((char *) mtmp); 226 mtmp = mtmp2; 227 } 228 bwrite(fd, (char *) &minusone, sizeof(int)); 229 } 230 #endif 231 232 savegoldchn(fd,gold) 233 register fd; 234 register struct gold *gold; 235 { 236 register struct gold *gold2; 237 while(gold) { 238 gold2 = gold->ngold; 239 bwrite(fd, (char *) gold, sizeof(struct gold)); 240 #ifdef DGK 241 if (!count_only) 242 #endif 243 free((char *) gold); 244 gold = gold2; 245 } 246 bwrite(fd, nul, sizeof(struct gold)); 247 } 248 249 savetrapchn(fd,trap) 250 register fd; 251 register struct trap *trap; 252 { 253 register struct trap *trap2; 254 while(trap) { 255 trap2 = trap->ntrap; 256 bwrite(fd, (char *) trap, sizeof(struct trap)); 257 #ifdef DGK 258 if (!count_only) 259 #endif 260 free((char *) trap); 261 trap = trap2; 262 } 263 bwrite(fd, nul, sizeof(struct trap)); 264 } 265 266 getlev(fd,pid,lev) 267 int fd,pid; 268 xchar lev; 269 { 270 register struct gold *gold; 271 register struct trap *trap; 272 #ifndef NOWORM 273 register struct wseg *wtmp; 274 #endif /* NOWORM /**/ 275 register tmp; 276 long omoves; 277 int hpid; 278 xchar dlvl; 279 #ifdef DGK 280 struct symbols osymbol; 281 int ovmajor, ovminor, x, y, up, dn, lt, rt; 282 uchar osym, nsym; 283 #endif 284 285 #ifdef MSDOS 286 setmode(fd,O_BINARY); 287 #endif 288 #ifdef DGK 289 /* Not yet used */ 290 mread(fd, (char *) &ovmajor, sizeof(ovmajor)); 291 mread(fd, (char *) &ovminor, sizeof(ovminor)); 292 #endif 293 /* First some sanity checks */ 294 mread(fd, (char *) &hpid, sizeof(hpid)); 295 mread(fd, (char *) &dlvl, sizeof(dlvl)); 296 if((pid && pid != hpid) || (lev && dlvl != lev)) { 297 pline("Strange, this map is not as I remember it."); 298 pline("Somebody is trying some trickery here ..."); 299 pline("This game is void ..."); 300 done("tricked"); 301 } 302 303 fgold = 0; 304 ftrap = 0; 305 mread(fd, (char *) levl, sizeof(levl)); 306 #ifdef DGK 307 /* Corners are poorly implemented. They only exist in the 308 * scrsym field of each dungeon element. So we have to go 309 * through the previous level, looking for scrsym with the 310 * old corner values, checking to make sure that they are 311 * where corners should be, then replace them with the scrsym 312 * of the new GRAPHICS character set. Ugly. 313 */ 314 mread(fd, (char *) &osymbol, sizeof(osymbol)); 315 if (memcmp((char *) &osymbol, (char *) &symbol, sizeof (symbol))) { 316 for (x = 0; x < COLNO; x++) 317 for (y = 0; y < ROWNO; y++) { 318 osym = levl[x][y].scrsym; 319 nsym = 0; 320 switch (levl[x][y].typ) { 321 case 0: 322 case SCORR: 323 break; 324 case ROOM: 325 if (osym == osymbol.room) 326 nsym = symbol.room; 327 break; 328 case DOOR: 329 if (osym == osymbol.door) 330 nsym = symbol.door; 331 break; 332 case CORR: 333 if (osym == osymbol.corr) 334 nsym = symbol.corr; 335 break; 336 case VWALL: 337 if (osym == osymbol.vwall) 338 nsym = symbol.vwall; 339 break; 340 case SDOOR: 341 if (osym == osymbol.vwall) 342 nsym = symbol.vwall; 343 else if (osym == osymbol.hwall) 344 nsym = symbol.hwall; 345 break; 346 /* Now the ugly stuff */ 347 case HWALL: 348 up = (y > 0) ? levl[x][y-1].typ : 0; 349 dn = (y < ROWNO-1) ?levl[x][y+1].typ : 0; 350 lt = (x > 0) ? levl[x-1][y].typ : 0; 351 rt = (x < COLNO-1) ?levl[x+1][y].typ : 0; 352 up = up && (up == VWALL || up == DOOR 353 || up == SDOOR); 354 dn = dn && (dn == VWALL || dn == DOOR 355 || dn == SDOOR); 356 lt = lt && (lt == HWALL || lt == DOOR 357 || lt == SDOOR); 358 rt = rt && (rt == HWALL || rt == DOOR 359 || rt == SDOOR); 360 if (rt && dn && osym == osymbol.tlcorn) 361 nsym = symbol.tlcorn; 362 else if (lt && dn && osym == osymbol.trcorn) 363 nsym = symbol.trcorn; 364 else if (rt && up && osym == osymbol.blcorn) 365 nsym = symbol.blcorn; 366 else if (lt && up && osym == osymbol.brcorn) 367 nsym = symbol.brcorn; 368 else if (osym == osymbol.hwall) 369 nsym = symbol.hwall; 370 break; 371 default: 372 break; 373 } 374 if (nsym) 375 levl[x][y].scrsym = nsym; 376 } 377 } 378 #endif 379 mread(fd, (char *)&omoves, sizeof(omoves)); 380 mread(fd, (char *)&xupstair, sizeof(xupstair)); 381 mread(fd, (char *)&yupstair, sizeof(yupstair)); 382 mread(fd, (char *)&xdnstair, sizeof(xdnstair)); 383 mread(fd, (char *)&ydnstair, sizeof(ydnstair)); 384 385 fmon = restmonchn(fd); 386 387 /* regenerate animals while on another level */ 388 { long tmoves = (moves > omoves) ? moves-omoves : 0; 389 register struct monst *mtmp, *mtmp2; 390 extern char genocided[]; 391 392 for(mtmp = fmon; mtmp; mtmp = mtmp2) { 393 long newhp; /* tmoves may be very large */ 394 395 mtmp2 = mtmp->nmon; 396 if(index(genocided, mtmp->data->mlet)) { 397 mondead(mtmp); 398 continue; 399 } 400 401 if(mtmp->mtame && tmoves > 250) { 402 mtmp->mtame = 0; 403 mtmp->mpeaceful = 0; 404 } 405 406 newhp = mtmp->mhp + 407 (index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20); 408 if(newhp > mtmp->mhpmax) 409 mtmp->mhp = mtmp->mhpmax; 410 else 411 mtmp->mhp = newhp; 412 } 413 } 414 415 setgd(); 416 gold = newgold(); 417 mread(fd, (char *)gold, sizeof(struct gold)); 418 while(gold->gx) { 419 gold->ngold = fgold; 420 fgold = gold; 421 gold = newgold(); 422 mread(fd, (char *)gold, sizeof(struct gold)); 423 } 424 free((char *) gold); 425 trap = newtrap(); 426 mread(fd, (char *)trap, sizeof(struct trap)); 427 while(trap->tx) { 428 trap->ntrap = ftrap; 429 ftrap = trap; 430 trap = newtrap(); 431 mread(fd, (char *)trap, sizeof(struct trap)); 432 } 433 free((char *) trap); 434 fobj = restobjchn(fd); 435 billobjs = restobjchn(fd); 436 rest_engravings(fd); 437 mread(fd, (char *)rooms, sizeof(rooms)); 438 mread(fd, (char *)doors, sizeof(doors)); 439 #ifndef NOWORM 440 mread(fd, (char *)wsegs, sizeof(wsegs)); 441 for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ 442 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 443 while(1) { 444 mread(fd, (char *)wtmp, sizeof(struct wseg)); 445 if(!wtmp->nseg) break; 446 wheads[tmp]->nseg = wtmp = newseg(); 447 wheads[tmp] = wtmp; 448 } 449 } 450 mread(fd, (char *)wgrowtime, sizeof(wgrowtime)); 451 #endif /* NOWORM /**/ 452 } 453 454 mread(fd, buf, len) 455 register fd; 456 register char *buf; 457 register unsigned len; 458 { 459 register int rlen; 460 extern boolean restoring; 461 462 rlen = read(fd, buf, (int) len); 463 if(rlen != len){ 464 pline("Read %d instead of %u bytes.\n", rlen, len); 465 if(restoring) { 466 (void) unlink(SAVEF); 467 error("Error restoring old game."); 468 } 469 panic("Error reading level file."); 470 } 471 } 472 473 mklev() 474 { 475 extern boolean in_mklev; 476 477 if(getbones()) return; 478 479 in_mklev = TRUE; 480 makelevel(); 481 in_mklev = FALSE; 482 } 483 484 485 #ifdef DGK 486 swapin_file(lev) { 487 char to[PATHLEN], from[PATHLEN]; 488 489 sprintf(from, "%s%s", permbones, alllevels); 490 sprintf(to, "%s%s", levels, alllevels); 491 name_file(from, lev); 492 name_file(to, lev); 493 while (fileinfo[lev].size > freediskspace(to)) 494 if (!swapout_oldest()) 495 return FALSE; 496 #ifdef WIZARD 497 if (wizard) { 498 pline("Swapping in `%s'", from); 499 fflush(stdout); 500 } 501 #endif 502 copyfile(from, to); 503 (void) unlink(from); 504 fileinfo[lev].where = ACTIVE; 505 return TRUE; 506 } 507 508 509 swapout_oldest() { 510 char to[PATHLEN], from[PATHLEN]; 511 int i, oldest; 512 long oldtime; 513 514 if (!ramdisk) 515 return FALSE; 516 for (i = 1, oldtime = 0, oldest = 0; i <= maxdlevel; i++) 517 if (fileinfo[i].where == ACTIVE 518 && (!oldtime || fileinfo[i].time < oldtime)) { 519 oldest = i; 520 oldtime = fileinfo[i].time; 521 } 522 if (!oldest) 523 return FALSE; 524 sprintf(from, "%s%s", levels, alllevels); 525 sprintf(to, "%s%s", permbones, alllevels); 526 name_file(from, oldest); 527 name_file(to, oldest); 528 #ifdef WIZARD 529 if (wizard) { 530 pline("Swapping out `%s'.", from); 531 fflush(stdout); 532 } 533 #endif 534 copyfile(from, to); 535 unlink(from); 536 fileinfo[oldest].where = SWAPPED; 537 return TRUE; 538 } 539 540 copyfile(from, to) 541 char *from, *to; 542 { 543 char buf[BUFSIZ]; 544 int nfrom, nto, fdfrom, fdto; 545 546 if ((fdfrom = open(from, O_RDONLY | O_BINARY | O_CREAT, FMASK)) < 0) 547 panic("Can't copy from %s !?", from); 548 if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT, FMASK)) < 0) 549 panic("Can't copy to %s", to); 550 do { 551 nfrom = read(fdfrom, buf, BUFSIZ); 552 nto = write(fdto, buf, nfrom); 553 if (nto != nfrom) 554 panic("Copyfile failed!"); 555 } while (nfrom == BUFSIZ); 556 close(fdfrom); 557 close(fdto); 558 } 559 #endif