Source:SLASH'EM 0.0.7E7F2/restore.c
Jump to navigation
Jump to search
Below is the full text to restore.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[Source:SLASH'EM 0.0.7E7F2/restore.c#line123]], for example.
Source code for vanilla NetHack is at Source code.
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)restore.c 3.4 2003/09/06 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "lev.h" 7. #include "tcap.h" /* for TERMLIB and ASCIIGRAPH */ 8. 9. #if defined(MICRO) 10. extern int dotcnt; /* shared with save */ 11. extern int dotrow; /* shared with save */ 12. #endif 13. 14. #ifdef USE_TILES 15. extern void FDECL(substitute_tiles, (d_level *)); /* from tile.c */ 16. #endif 17. 18. #ifdef ZEROCOMP 19. static int NDECL(mgetc); 20. #endif 21. STATIC_DCL void NDECL(find_lev_obj); 22. STATIC_DCL void FDECL(restlevchn, (int)); 23. STATIC_DCL void FDECL(restdamage, (int,BOOLEAN_P)); 24. STATIC_DCL struct obj *FDECL(restobjchn, (int,BOOLEAN_P,BOOLEAN_P)); 25. STATIC_DCL struct monst *FDECL(restmonchn, (int,BOOLEAN_P)); 26. STATIC_DCL struct fruit *FDECL(loadfruitchn, (int)); 27. STATIC_DCL void FDECL(freefruitchn, (struct fruit *)); 28. STATIC_DCL void FDECL(ghostfruit, (struct obj *)); 29. STATIC_DCL boolean FDECL(restgamestate, (int, unsigned int *, unsigned int *)); 30. STATIC_DCL void FDECL(restlevelstate, (unsigned int, unsigned int)); 31. STATIC_DCL int FDECL(restlevelfile, (int,XCHAR_P)); 32. STATIC_DCL void FDECL(reset_oattached_mids, (BOOLEAN_P)); 33. 34. /* 35. * Save a mapping of IDs from ghost levels to the current level. This 36. * map is used by the timer routines when restoring ghost levels. 37. */ 38. #define N_PER_BUCKET 64 39. struct bucket { 40. struct bucket *next; 41. struct { 42. unsigned gid; /* ghost ID */ 43. unsigned nid; /* new ID */ 44. } map[N_PER_BUCKET]; 45. }; 46. 47. STATIC_DCL void NDECL(clear_id_mapping); 48. STATIC_DCL void FDECL(add_id_mapping, (unsigned, unsigned)); 49. 50. static int n_ids_mapped = 0; 51. static struct bucket *id_map = 0; 52. 53. 54. #ifdef AMII_GRAPHICS 55. void FDECL( amii_setpens, (int) ); /* use colors from save file */ 56. extern int amii_numcolors; 57. #endif 58. 59. #include "quest.h" 60. 61. boolean restoring = FALSE; 62. static NEARDATA struct fruit *oldfruit; 63. static NEARDATA long omoves; 64. 65. #define Is_IceBox(o) ((o)->otyp == ICE_BOX ? TRUE : FALSE) 66. 67. /* Recalculate level.objects[x][y], since this info was not saved. */ 68. STATIC_OVL void 69. find_lev_obj() 70. { 71. register struct obj *fobjtmp = (struct obj *)0; 72. register struct obj *otmp; 73. int x,y; 74. 75. for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) 76. level.objects[x][y] = (struct obj *)0; 77. 78. /* 79. * Reverse the entire fobj chain, which is necessary so that we can 80. * place the objects in the proper order. Make all obj in chain 81. * OBJ_FREE so place_object will work correctly. 82. */ 83. while ((otmp = fobj) != 0) { 84. fobj = otmp->nobj; 85. otmp->nobj = fobjtmp; 86. otmp->where = OBJ_FREE; 87. fobjtmp = otmp; 88. } 89. /* fobj should now be empty */ 90. 91. /* Set level.objects (as well as reversing the chain back again) */ 92. while ((otmp = fobjtmp) != 0) { 93. fobjtmp = otmp->nobj; 94. place_object(otmp, otmp->ox, otmp->oy); 95. } 96. } 97. 98. /* Things that were marked "in_use" when the game was saved (ex. via the 99. * infamous "HUP" cheat) get used up here. 100. */ 101. void 102. inven_inuse(quietly) 103. boolean quietly; 104. { 105. register struct obj *otmp, *otmp2; 106. 107. for (otmp = invent; otmp; otmp = otmp2) { 108. otmp2 = otmp->nobj; 109. #ifndef GOLDOBJ 110. if (otmp->oclass == COIN_CLASS) { 111. /* in_use gold is created by some menu operations */ 112. if (!otmp->in_use) { 113. impossible("inven_inuse: !in_use gold in inventory"); 114. } 115. extract_nobj(otmp, &invent); 116. otmp->in_use = FALSE; 117. dealloc_obj(otmp); 118. } else 119. #endif /* GOLDOBJ */ 120. if (otmp->in_use) { 121. if (!quietly) pline("Finishing off %s...", xname(otmp)); 122. useup(otmp); 123. } 124. } 125. } 126. 127. STATIC_OVL void 128. restlevchn(fd) 129. register int fd; 130. { 131. int cnt; 132. s_level *tmplev, *x; 133. 134. sp_levchn = (s_level *) 0; 135. mread(fd, (genericptr_t) &cnt, sizeof(int)); 136. for(; cnt > 0; cnt--) { 137. 138. tmplev = (s_level *)alloc(sizeof(s_level)); 139. mread(fd, (genericptr_t) tmplev, sizeof(s_level)); 140. if(!sp_levchn) sp_levchn = tmplev; 141. else { 142. 143. for(x = sp_levchn; x->next; x = x->next); 144. x->next = tmplev; 145. } 146. tmplev->next = (s_level *)0; 147. } 148. } 149. 150. STATIC_OVL void 151. restdamage(fd, ghostly) 152. int fd; 153. boolean ghostly; 154. { 155. int counter; 156. struct damage *tmp_dam; 157. 158. mread(fd, (genericptr_t) &counter, sizeof(counter)); 159. if (!counter) 160. return; 161. tmp_dam = (struct damage *)alloc(sizeof(struct damage)); 162. while (--counter >= 0) { 163. char damaged_shops[5], *shp = (char *)0; 164. 165. mread(fd, (genericptr_t) tmp_dam, sizeof(*tmp_dam)); 166. if (ghostly) 167. tmp_dam->when += (monstermoves - omoves); 168. Strcpy(damaged_shops, 169. in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE)); 170. if (u.uz.dlevel) { 171. /* when restoring, there are two passes over the current 172. * level. the first time, u.uz isn't set, so neither is 173. * shop_keeper(). just wait and process the damage on 174. * the second pass. 175. */ 176. for (shp = damaged_shops; *shp; shp++) { 177. struct monst *shkp = shop_keeper(*shp); 178. 179. if (shkp && inhishop(shkp) && 180. repair_damage(shkp, tmp_dam, TRUE)) 181. break; 182. } 183. } 184. if (!shp || !*shp) { 185. tmp_dam->next = level.damagelist; 186. level.damagelist = tmp_dam; 187. tmp_dam = (struct damage *)alloc(sizeof(*tmp_dam)); 188. } 189. } 190. free((genericptr_t)tmp_dam); 191. } 192. 193. STATIC_OVL struct obj * 194. restobjchn(fd, ghostly, frozen) 195. register int fd; 196. boolean ghostly, frozen; 197. { 198. register struct obj *otmp, *otmp2 = 0; 199. register struct obj *first = (struct obj *)0; 200. int xl; 201. 202. while(1) { 203. mread(fd, (genericptr_t) &xl, sizeof(xl)); 204. if(xl == -1) break; 205. otmp = newobj(xl); 206. if(!first) first = otmp; 207. else otmp2->nobj = otmp; 208. mread(fd, (genericptr_t) otmp, 209. (unsigned) xl + sizeof(struct obj)); 210. if (ghostly) { 211. unsigned nid = flags.ident++; 212. add_id_mapping(otmp->o_id, nid); 213. otmp->o_id = nid; 214. } 215. if (ghostly && otmp->otyp == SLIME_MOLD) ghostfruit(otmp); 216. /* Ghost levels get object age shifted from old player's clock 217. * to new player's clock. Assumption: new player arrived 218. * immediately after old player died. 219. */ 220. if (ghostly && !frozen && !age_is_relative(otmp)) 221. otmp->age = monstermoves - omoves + otmp->age; 222. 223. /* get contents of a container or statue */ 224. if (Has_contents(otmp)) { 225. struct obj *otmp3; 226. otmp->cobj = restobjchn(fd, ghostly, Is_IceBox(otmp)); 227. /* restore container back pointers */ 228. for (otmp3 = otmp->cobj; otmp3; otmp3 = otmp3->nobj) 229. otmp3->ocontainer = otmp; 230. } 231. if (otmp->bypass) otmp->bypass = 0; 232. 233. otmp2 = otmp; 234. } 235. if(first && otmp2->nobj){ 236. impossible("Restobjchn: error reading objchn."); 237. otmp2->nobj = 0; 238. } 239. 240. return(first); 241. } 242. 243. STATIC_OVL struct monst * 244. restmonchn(fd, ghostly) 245. register int fd; 246. boolean ghostly; 247. { 248. register struct monst *mtmp, *mtmp2 = 0; 249. register struct monst *first = (struct monst *)0; 250. int xl; 251. struct permonst *monbegin; 252. boolean moved; 253. 254. /* get the original base address */ 255. mread(fd, (genericptr_t)&monbegin, sizeof(monbegin)); 256. moved = (monbegin != mons); 257. 258. while(1) { 259. mread(fd, (genericptr_t) &xl, sizeof(xl)); 260. if(xl == -1) break; 261. mtmp = newmonst(xl); 262. if(!first) first = mtmp; 263. else mtmp2->nmon = mtmp; 264. mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst)); 265. if (ghostly) { 266. unsigned nid = flags.ident++; 267. add_id_mapping(mtmp->m_id, nid); 268. mtmp->m_id = nid; 269. } 270. if (moved && mtmp->data) { 271. int offset = mtmp->data - monbegin; /*(ptrdiff_t)*/ 272. mtmp->data = mons + offset; /* new permonst location */ 273. } 274. if (ghostly) { 275. int mndx = monsndx(mtmp->data); 276. if (propagate(mndx, TRUE, ghostly) == 0) { 277. /* cookie to trigger purge in getbones() */ 278. mtmp->mhpmax = DEFUNCT_MONSTER; 279. } 280. } 281. if(mtmp->minvent) { 282. struct obj *obj; 283. mtmp->minvent = restobjchn(fd, ghostly, FALSE); 284. /* restore monster back pointer */ 285. for (obj = mtmp->minvent; obj; obj = obj->nobj) 286. obj->ocarry = mtmp; 287. } 288. if (mtmp->mw) { 289. struct obj *obj; 290. 291. for(obj = mtmp->minvent; obj; obj = obj->nobj) 292. if (obj->owornmask & W_WEP) break; 293. if (obj) mtmp->mw = obj; 294. else { 295. MON_NOWEP(mtmp); 296. /* KMH -- this is more an annoyance than a bug */ 297. /* impossible("bad monster weapon restore"); */ 298. } 299. } 300. 301. if (mtmp->isshk) restshk(mtmp, ghostly); 302. if (mtmp->ispriest) restpriest(mtmp, ghostly); 303. if (mtmp->isgyp && ghostly) gypsy_init(mtmp); 304. 305. mtmp2 = mtmp; 306. } 307. if(first && mtmp2->nmon){ 308. impossible("Restmonchn: error reading monchn."); 309. mtmp2->nmon = 0; 310. } 311. return(first); 312. } 313. 314. STATIC_OVL struct fruit * 315. loadfruitchn(fd) 316. int fd; 317. { 318. register struct fruit *flist, *fnext; 319. 320. flist = 0; 321. while (fnext = newfruit(), 322. mread(fd, (genericptr_t)fnext, sizeof *fnext), 323. fnext->fid != 0) { 324. fnext->nextf = flist; 325. flist = fnext; 326. } 327. dealloc_fruit(fnext); 328. return flist; 329. } 330. 331. STATIC_OVL void 332. freefruitchn(flist) 333. register struct fruit *flist; 334. { 335. register struct fruit *fnext; 336. 337. while (flist) { 338. fnext = flist->nextf; 339. dealloc_fruit(flist); 340. flist = fnext; 341. } 342. } 343. 344. STATIC_OVL void 345. ghostfruit(otmp) 346. register struct obj *otmp; 347. { 348. register struct fruit *oldf; 349. 350. for (oldf = oldfruit; oldf; oldf = oldf->nextf) 351. if (oldf->fid == otmp->spe) break; 352. 353. if (!oldf) impossible("no old fruit?"); 354. else otmp->spe = fruitadd(oldf->fname); 355. } 356. 357. STATIC_OVL 358. boolean 359. restgamestate(fd, stuckid, steedid) 360. register int fd; 361. unsigned int *stuckid, *steedid; /* STEED */ 362. { 363. /* discover is actually flags.explore */ 364. boolean remember_discover = discover; 365. struct obj *otmp; 366. int uid; 367. 368. mread(fd, (genericptr_t) &uid, sizeof uid); 369. if (uid != getuid()) { /* strange ... */ 370. /* for wizard mode, issue a reminder; for others, treat it 371. as an attempt to cheat and refuse to restore this file */ 372. pline("Saved game was not yours."); 373. #ifdef WIZARD 374. if(!wizard) 375. #endif 376. return FALSE; 377. } 378. 379. mread(fd, (genericptr_t) &flags, sizeof(struct flag)); 380. flags.bypasses = 0; /* never use the saved value of bypasses */ 381. if (remember_discover) discover = remember_discover; 382. 383. role_init(); /* Reset the initial role, gender, and alignment */ 384. 385. #ifdef AMII_GRAPHICS 386. amii_setpens(amii_numcolors); /* use colors from save file */ 387. #endif 388. mread(fd, (genericptr_t) &u, sizeof(struct you)); 389. init_uasmon(); 390. #ifdef CLIPPING 391. cliparound(u.ux, u.uy); 392. #endif 393. if(u.uhp <= 0 && (!Upolyd || u.mh <= 0)) { 394. u.ux = u.uy = 0; /* affects pline() [hence You()] */ 395. You("were not healthy enough to survive restoration."); 396. /* wiz1_level.dlevel is used by mklev.c to see if lots of stuff is 397. * uninitialized, so we only have to set it and not the other stuff. 398. */ 399. wiz1_level.dlevel = 0; 400. u.uz.dnum = 0; 401. u.uz.dlevel = 1; 402. return(FALSE); 403. } 404. 405. /* this stuff comes after potential aborted restore attempts */ 406. restore_timers(fd, RANGE_GLOBAL, FALSE, 0L); 407. restore_light_sources(fd); 408. invent = restobjchn(fd, FALSE, FALSE); 409. migrating_objs = restobjchn(fd, FALSE, FALSE); 410. migrating_mons = restmonchn(fd, FALSE); 411. mread(fd, (genericptr_t) mvitals, sizeof(mvitals)); 412. 413. /* 414. * There are some things after this that can have unintended display 415. * side-effects too early in the game. 416. * Disable see_monsters() here, re-enable it at the top of moveloop() 417. */ 418. defer_see_monsters = TRUE; 419. 420. /* this comes after inventory has been loaded */ 421. for(otmp = invent; otmp; otmp = otmp->nobj) 422. if(otmp->owornmask) 423. #ifdef DEBUG 424. { 425. pline ("obj(%s),", xname(otmp)); 426. #endif 427. setworn(otmp, otmp->owornmask); 428. #ifdef DEBUG 429. } 430. #endif 431. /* reset weapon so that player will get a reminder about "bashing" 432. during next fight when bare-handed or wielding an unconventional 433. item; for pick-axe, we aren't able to distinguish between having 434. applied or wielded it, so be conservative and assume the former */ 435. otmp = uwep; /* `uwep' usually init'd by setworn() in loop above */ 436. uwep = 0; /* clear it and have setuwep() reinit */ 437. setuwep(otmp,FALSE); /* (don't need any null check here) */ 438. /* KMH, balance patch -- added fishing pole */ 439. if (!uwep || uwep->otyp == PICK_AXE || uwep->otyp == GRAPPLING_HOOK || 440. uwep->otyp == FISHING_POLE) 441. unweapon = TRUE; 442. 443. restore_dungeon(fd); 444. 445. restlevchn(fd); 446. mread(fd, (genericptr_t) &moves, sizeof moves); 447. mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves); 448. mread(fd, (genericptr_t) &quest_status, sizeof(struct q_score)); 449. mread(fd, (genericptr_t) spl_book, 450. sizeof(struct spell) * (MAXSPELL + 1)); 451. mread(fd, (genericptr_t) tech_list, 452. sizeof(struct tech) * (MAXTECH + 1)); 453. restore_artifacts(fd); 454. restore_oracles(fd); 455. if (u.ustuck) 456. mread(fd, (genericptr_t) stuckid, sizeof (*stuckid)); 457. #ifdef STEED 458. if (u.usteed) 459. mread(fd, (genericptr_t) steedid, sizeof (*steedid)); 460. #endif 461. mread(fd, (genericptr_t) pl_character, sizeof (pl_character)); 462. 463. mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); 464. mread(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit); 465. freefruitchn(ffruit); /* clean up fruit(s) made by initoptions() */ 466. ffruit = loadfruitchn(fd); 467. 468. restnames(fd); 469. restore_waterlevel(fd); 470. /* must come after all mons & objs are restored */ 471. relink_timers(FALSE); 472. relink_light_sources(FALSE); 473. return(TRUE); 474. } 475. 476. /* update game state pointers to those valid for the current level (so we 477. * don't dereference a wild u.ustuck when saving the game state, for instance) 478. */ 479. STATIC_OVL void 480. restlevelstate(stuckid, steedid) 481. unsigned int stuckid, steedid; /* STEED */ 482. { 483. register struct monst *mtmp; 484. 485. if (stuckid) { 486. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 487. if (mtmp->m_id == stuckid) break; 488. if (!mtmp) panic("Cannot find the monster ustuck."); 489. setustuck(mtmp); 490. } 491. #ifdef STEED 492. if (steedid) { 493. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 494. if (mtmp->m_id == steedid) break; 495. if (!mtmp) panic("Cannot find the monster usteed."); 496. u.usteed = mtmp; 497. remove_monster(mtmp->mx, mtmp->my); 498. } 499. #endif 500. } 501. 502. /*ARGSUSED*/ /* fd used in MFLOPPY only */ 503. STATIC_OVL int 504. restlevelfile(fd, ltmp) 505. register int fd; 506. xchar ltmp; 507. { 508. #ifdef MAC_MPW 509. # pragma unused(fd) 510. #endif 511. register int nfd; 512. char whynot[BUFSZ]; 513. 514. nfd = create_levelfile(ltmp, whynot); 515. if (nfd < 0) { 516. /* BUG: should suppress any attempt to write a panic 517. save file if file creation is now failing... */ 518. panic("restlevelfile: %s", whynot); 519. } 520. #ifdef MFLOPPY 521. if (!savelev(nfd, ltmp, COUNT_SAVE)) { 522. 523. /* The savelev can't proceed because the size required 524. * is greater than the available disk space. 525. */ 526. pline("Not enough space on `%s' to restore your game.", 527. levels); 528. 529. /* Remove levels and bones that may have been created. 530. */ 531. (void) close(nfd); 532. # ifdef AMIGA 533. clearlocks(); 534. # else 535. eraseall(levels, alllevels); 536. eraseall(levels, allbones); 537. 538. /* Perhaps the person would like to play without a 539. * RAMdisk. 540. */ 541. /* Maybe not [Tom] */ 542. #if 0 543. if (ramdisk) { 544. /* PlaywoRAMdisk may not return, but if it does 545. * it is certain that ramdisk will be 0. 546. */ 547. playwoRAMdisk(); 548. /* Rewind save file and try again */ 549. (void) lseek(fd, (off_t)0, 0); 550. (void) uptodate(fd, (char *)0); /* skip version */ 551. return dorecover(fd); /* 0 or 1 */ 552. } else 553. #endif 554. { 555. # endif 556. pline("Be seeing you..."); 557. terminate(EXIT_SUCCESS); 558. # ifndef AMIGA 559. } 560. # endif 561. } 562. #endif 563. bufon(nfd); 564. savelev(nfd, ltmp, WRITE_SAVE | FREE_SAVE); 565. bclose(nfd); 566. return(2); 567. } 568. 569. int 570. dorecover(fd) 571. register int fd; 572. { 573. unsigned int stuckid = 0, steedid = 0; /* not a register */ 574. xchar ltmp; 575. int rtmp; 576. struct obj *otmp; 577. 578. #ifdef STORE_PLNAME_IN_FILE 579. mread(fd, (genericptr_t) plname, PL_NSIZ); 580. #endif 581. 582. restoring = TRUE; 583. getlev(fd, 0, (xchar)0, FALSE); 584. if (!restgamestate(fd, &stuckid, &steedid)) { 585. display_nhwindow(WIN_MESSAGE, TRUE); 586. savelev(-1, 0, FREE_SAVE); /* discard current level */ 587. (void) close(fd); 588. (void) delete_savefile(); 589. restoring = FALSE; 590. return(0); 591. } 592. restlevelstate(stuckid, steedid); 593. #ifdef INSURANCE 594. savestateinlock(); 595. #endif 596. rtmp = restlevelfile(fd, ledger_no(&u.uz)); 597. if (rtmp < 2) return(rtmp); /* dorecover called recursively */ 598. 599. /* these pointers won't be valid while we're processing the 600. * other levels, but they'll be reset again by restlevelstate() 601. * afterwards, and in the meantime at least u.usteed may mislead 602. * place_monster() on other levels 603. */ 604. setustuck((struct monst *)0); 605. #ifdef STEED 606. u.usteed = (struct monst *)0; 607. #endif 608. 609. #ifdef MICRO 610. # ifdef AMII_GRAPHICS 611. { 612. extern struct window_procs amii_procs; 613. if(windowprocs.win_init_nhwindows== amii_procs.win_init_nhwindows){ 614. extern winid WIN_BASE; 615. clear_nhwindow(WIN_BASE); /* hack until there's a hook for this */ 616. } 617. } 618. # else 619. clear_nhwindow(WIN_MAP); 620. # endif 621. clear_nhwindow(WIN_MESSAGE); 622. /* moved lower */ 623. curs(WIN_MAP, 1, 1); 624. dotcnt = 0; 625. dotrow = 2; 626. # ifdef TTY_GRAPHICS 627. if (!strncmpi("tty", windowprocs.name, 3)) 628. putstr(WIN_MAP, 0, "Restoring:"); 629. # endif 630. #endif 631. while(1) { 632. #ifdef ZEROCOMP 633. if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0) 634. #else 635. if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp) 636. #endif 637. break; 638. getlev(fd, 0, ltmp, FALSE); 639. #if defined(MICRO) && defined(TTY_GRAPHICS) 640. if (!strncmpi("tty", windowprocs.name, 3)) { 641. curs(WIN_MAP, 1+dotcnt++, dotrow); 642. if (dotcnt >= (COLNO - 1)) { 643. dotrow++; 644. dotcnt = 0; 645. } 646. putstr(WIN_MAP, 0, "."); 647. mark_synch(); 648. } 649. #endif 650. rtmp = restlevelfile(fd, ltmp); 651. if (rtmp < 2) return(rtmp); /* dorecover called recursively */ 652. } 653. 654. #ifdef BSD 655. (void) lseek(fd, 0L, 0); 656. #else 657. (void) lseek(fd, 0L, 0); 658. /* (void) lseek(fd, (off_t)0, 0); */ 659. #endif 660. (void) uptodate(fd, (char *)0); /* skip version info */ 661. #ifdef STORE_PLNAME_IN_FILE 662. mread(fd, (genericptr_t) plname, PL_NSIZ); 663. #endif 664. getlev(fd, 0, (xchar)0, FALSE); 665. (void) close(fd); 666. 667. if (!wizard && !discover) 668. (void) delete_savefile(); 669. #ifdef REINCARNATION 670. if (Is_rogue_level(&u.uz)) assign_rogue_graphics(TRUE); 671. #endif 672. #ifdef USE_TILES 673. substitute_tiles(&u.uz); 674. #endif 675. restlevelstate(stuckid, steedid); 676. 677. /* WAC -- This needs to be after the second restlevelstate 678. * You() writes to the message line, which also updates the 679. * status line. However, u.usteed needs to be corrected or else 680. * weight/carrying capacities will be calculated by dereferencing 681. * garbage pointers. 682. * Side effect of this is that you don't see this message until after the 683. * all the levels are loaded 684. */ 685. You("return to level %d in %s%s.", 686. depth(&u.uz), dungeons[u.uz.dnum].dname, 687. flags.debug ? " while in debug mode" : 688. flags.explore ? " while in explore mode" : ""); 689. 690. #ifdef MFLOPPY 691. gameDiskPrompt(); 692. #endif 693. max_rank_sz(); /* to recompute mrank_sz (botl.c) */ 694. /* take care of iron ball & chain */ 695. for(otmp = fobj; otmp; otmp = otmp->nobj) 696. if(otmp->owornmask) 697. setworn(otmp, otmp->owornmask); 698. 699. /* in_use processing must be after: 700. * + The inventory has been read so that freeinv() works. 701. * + The current level has been restored so billing information 702. * is available. 703. */ 704. inven_inuse(FALSE); 705. 706. load_qtlist(); /* re-load the quest text info */ 707. reset_attribute_clock(); 708. /* Set up the vision internals, after levl[] data is loaded */ 709. /* but before docrt(). */ 710. vision_reset(); 711. vision_full_recalc = 1; /* recompute vision (not saved) */ 712. 713. run_timers(); /* expire all timers that have gone off while away */ 714. docrt(); 715. restoring = FALSE; 716. clear_nhwindow(WIN_MESSAGE); 717. program_state.something_worth_saving++; /* useful data now exists */ 718. 719. /* Success! */ 720. welcome(FALSE); 721. return(1); 722. } 723. 724. void 725. trickery(reason) 726. char *reason; 727. { 728. pline("Strange, this map is not as I remember it."); 729. pline("Somebody is trying some trickery here..."); 730. pline("This game is void."); 731. killer = reason; 732. done(TRICKED); 733. } 734. 735. void 736. getlev(fd, pid, lev, ghostly) 737. int fd, pid; 738. xchar lev; 739. boolean ghostly; 740. { 741. register struct trap *trap; 742. register struct monst *mtmp; 743. branch *br; 744. int hpid; 745. xchar dlvl; 746. int x, y; 747. #ifdef TOS 748. short tlev; 749. #endif 750. 751. if (ghostly) 752. clear_id_mapping(); 753. 754. #if defined(MSDOS) || defined(OS2) 755. setmode(fd, O_BINARY); 756. #endif 757. /* Load the old fruit info. We have to do it first, so the 758. * information is available when restoring the objects. 759. */ 760. if (ghostly) oldfruit = loadfruitchn(fd); 761. 762. /* First some sanity checks */ 763. mread(fd, (genericptr_t) &hpid, sizeof(hpid)); 764. /* CHECK: This may prevent restoration */ 765. #ifdef TOS 766. mread(fd, (genericptr_t) &tlev, sizeof(tlev)); 767. dlvl=tlev&0x00ff; 768. #else 769. mread(fd, (genericptr_t) &dlvl, sizeof(dlvl)); 770. #endif 771. if ((pid && pid != hpid) || (lev && dlvl != lev)) { 772. char trickbuf[BUFSZ]; 773. 774. if (pid && pid != hpid) 775. Sprintf(trickbuf, "PID (%d) doesn't match saved PID (%d)!", 776. hpid, pid); 777. else 778. Sprintf(trickbuf, "This is level %d, not %d!", dlvl, lev); 779. #ifdef WIZARD 780. if (wizard) pline(trickbuf); 781. #endif 782. trickery(trickbuf); 783. } 784. 785. #ifdef RLECOMP 786. { 787. short i, j; 788. uchar len; 789. struct rm r; 790. 791. #if defined(MAC) 792. /* Suppress warning about used before set */ 793. (void) memset((genericptr_t) &r, 0, sizeof(r)); 794. #endif 795. i = 0; j = 0; len = 0; 796. while(i < ROWNO) { 797. while(j < COLNO) { 798. if(len > 0) { 799. levl[j][i] = r; 800. len -= 1; 801. j += 1; 802. } else { 803. mread(fd, (genericptr_t)&len, sizeof(uchar)); 804. mread(fd, (genericptr_t)&r, sizeof(struct rm)); 805. } 806. } 807. j = 0; 808. i += 1; 809. } 810. } 811. #else 812. mread(fd, (genericptr_t) levl, sizeof(levl)); 813. #endif /* RLECOMP */ 814. 815. mread(fd, (genericptr_t)&omoves, sizeof(omoves)); 816. mread(fd, (genericptr_t)&upstair, sizeof(stairway)); 817. mread(fd, (genericptr_t)&dnstair, sizeof(stairway)); 818. mread(fd, (genericptr_t)&upladder, sizeof(stairway)); 819. mread(fd, (genericptr_t)&dnladder, sizeof(stairway)); 820. mread(fd, (genericptr_t)&sstairs, sizeof(stairway)); 821. mread(fd, (genericptr_t)&updest, sizeof(dest_area)); 822. mread(fd, (genericptr_t)&dndest, sizeof(dest_area)); 823. mread(fd, (genericptr_t)&level.flags, sizeof(level.flags)); 824. mread(fd, (genericptr_t)doors, sizeof(doors)); 825. rest_rooms(fd); /* No joke :-) */ 826. /* ALI - regenerate doorindex */ 827. if (nroom) 828. doorindex = rooms[nroom - 1].fdoor + rooms[nroom - 1].doorct; 829. else { 830. doorindex = 0; 831. for (y = 0; y < ROWNO; y++) 832. for (x = 0; x < COLNO; x++) 833. if (IS_DOOR(levl[x][y].typ)) 834. doorindex++; 835. } 836. 837. restore_timers(fd, RANGE_LEVEL, ghostly, monstermoves - omoves); 838. restore_light_sources(fd); 839. fmon = restmonchn(fd, ghostly); 840. 841. /* regenerate animals while on another level */ 842. if (u.uz.dlevel) { 843. register struct monst *mtmp2; 844. 845. for(mtmp = fmon; mtmp; mtmp = mtmp2) { 846. mtmp2 = mtmp->nmon; 847. if (ghostly) { 848. /* reset peaceful/malign relative to new character */ 849. if(!mtmp->isshk) 850. /* shopkeepers will reset based on name */ 851. mtmp->mpeaceful = peace_minded(mtmp->data); 852. set_malign(mtmp); 853. } else if (monstermoves > omoves) 854. mon_catchup_elapsed_time(mtmp, monstermoves - omoves); 855. 856. /* update shape-changers in case protection against 857. them is different now than when the level was saved */ 858. restore_cham(mtmp); 859. } 860. } 861. 862. rest_worm(fd); /* restore worm information */ 863. ftrap = 0; 864. while (trap = newtrap(), 865. mread(fd, (genericptr_t)trap, sizeof(struct trap)), 866. trap->tx != 0) { /* need "!= 0" to work around DICE 3.0 bug */ 867. trap->ntrap = ftrap; 868. ftrap = trap; 869. } 870. dealloc_trap(trap); 871. fobj = restobjchn(fd, ghostly, FALSE); 872. find_lev_obj(); 873. /* restobjchn()'s `frozen' argument probably ought to be a callback 874. routine so that we can check for objects being buried under ice */ 875. level.buriedobjlist = restobjchn(fd, ghostly, FALSE); 876. billobjs = restobjchn(fd, ghostly, FALSE); 877. rest_engravings(fd); 878. 879. /* reset level.monsters for new level */ 880. for (x = 0; x < COLNO; x++) 881. for (y = 0; y < ROWNO; y++) 882. level.monsters[x][y] = (struct monst *) 0; 883. for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon) { 884. if (mtmp->isshk) 885. set_residency(mtmp, FALSE); 886. place_monster(mtmp, mtmp->mx, mtmp->my); 887. if (mtmp->wormno) place_wsegs(mtmp); 888. } 889. restdamage(fd, ghostly); 890. 891. rest_regions(fd, ghostly); 892. if (ghostly) { 893. /* Now get rid of all the temp fruits... */ 894. freefruitchn(oldfruit), oldfruit = 0; 895. 896. if (lev > ledger_no(&medusa_level) && 897. lev < ledger_no(&stronghold_level) && xdnstair == 0) { 898. coord cc; 899. 900. mazexy(&cc); 901. xdnstair = cc.x; 902. ydnstair = cc.y; 903. levl[cc.x][cc.y].typ = STAIRS; 904. } 905. 906. br = Is_branchlev(&u.uz); 907. if (br && u.uz.dlevel == 1) { 908. d_level ltmp; 909. 910. if (on_level(&u.uz, &br->end1)) 911. assign_level(<mp, &br->end2); 912. else 913. assign_level(<mp, &br->end1); 914. 915. switch(br->type) { 916. case BR_STAIR: 917. case BR_NO_END1: 918. case BR_NO_END2: /* OK to assign to sstairs if it's not used */ 919. assign_level(&sstairs.tolev, <mp); 920. break; 921. case BR_PORTAL: /* max of 1 portal per level */ 922. { 923. register struct trap *ttmp; 924. for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 925. if (ttmp->ttyp == MAGIC_PORTAL) 926. break; 927. if (!ttmp) panic("getlev: need portal but none found"); 928. assign_level(&ttmp->dst, <mp); 929. } 930. break; 931. } 932. } else if (!br) { 933. /* Remove any dangling portals. */ 934. register struct trap *ttmp; 935. for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 936. if (ttmp->ttyp == MAGIC_PORTAL) { 937. deltrap(ttmp); 938. break; /* max of 1 portal/level */ 939. } 940. } 941. } 942. 943. /* must come after all mons & objs are restored */ 944. relink_timers(ghostly); 945. relink_light_sources(ghostly); 946. reset_oattached_mids(ghostly); 947. #ifdef DUNGEON_GROWTH 948. if (!ghostly) catchup_dgn_growths((monstermoves - omoves) / 5); 949. #endif 950. if (ghostly) 951. clear_id_mapping(); 952. } 953. 954. 955. /* Clear all structures for object and monster ID mapping. */ 956. STATIC_OVL void 957. clear_id_mapping() 958. { 959. struct bucket *curr; 960. 961. while ((curr = id_map) != 0) { 962. id_map = curr->next; 963. free((genericptr_t) curr); 964. } 965. n_ids_mapped = 0; 966. } 967. 968. /* Add a mapping to the ID map. */ 969. STATIC_OVL void 970. add_id_mapping(gid, nid) 971. unsigned gid, nid; 972. { 973. int idx; 974. 975. idx = n_ids_mapped % N_PER_BUCKET; 976. /* idx is zero on first time through, as well as when a new bucket is */ 977. /* needed */ 978. if (idx == 0) { 979. struct bucket *gnu = (struct bucket *) alloc(sizeof(struct bucket)); 980. gnu->next = id_map; 981. id_map = gnu; 982. } 983. 984. id_map->map[idx].gid = gid; 985. id_map->map[idx].nid = nid; 986. n_ids_mapped++; 987. } 988. 989. /* 990. * Global routine to look up a mapping. If found, return TRUE and fill 991. * in the new ID value. Otherwise, return false and return -1 in the new 992. * ID. 993. */ 994. boolean 995. lookup_id_mapping(gid, nidp) 996. unsigned gid, *nidp; 997. { 998. int i; 999. struct bucket *curr; 1000. 1001. if (n_ids_mapped) 1002. for (curr = id_map; curr; curr = curr->next) { 1003. /* first bucket might not be totally full */ 1004. if (curr == id_map) { 1005. i = n_ids_mapped % N_PER_BUCKET; 1006. if (i == 0) i = N_PER_BUCKET; 1007. } else 1008. i = N_PER_BUCKET; 1009. 1010. while (--i >= 0) 1011. if (gid == curr->map[i].gid) { 1012. *nidp = curr->map[i].nid; 1013. return TRUE; 1014. } 1015. } 1016. 1017. return FALSE; 1018. } 1019. 1020. STATIC_OVL void 1021. reset_oattached_mids(ghostly) 1022. boolean ghostly; 1023. { 1024. struct obj *otmp; 1025. unsigned oldid, nid; 1026. for (otmp = fobj; otmp; otmp = otmp->nobj) { 1027. if (ghostly && otmp->oattached == OATTACHED_MONST && otmp->oxlth) { 1028. struct monst *mtmp = (struct monst *)otmp->oextra; 1029. 1030. mtmp->m_id = 0; 1031. mtmp->mpeaceful = mtmp->mtame = 0; /* pet's owner died! */ 1032. } 1033. if (ghostly && otmp->oattached == OATTACHED_M_ID) { 1034. (void) memcpy((genericptr_t)&oldid, (genericptr_t)otmp->oextra, 1035. sizeof(oldid)); 1036. if (lookup_id_mapping(oldid, &nid)) 1037. (void) memcpy((genericptr_t)otmp->oextra, (genericptr_t)&nid, 1038. sizeof(nid)); 1039. else 1040. otmp->oattached = OATTACHED_NOTHING; 1041. } 1042. } 1043. } 1044. 1045. 1046. #ifdef ZEROCOMP 1047. #define RLESC '\0' /* Leading character for run of RLESC's */ 1048. 1049. #ifndef ZEROCOMP_BUFSIZ 1050. #define ZEROCOMP_BUFSIZ BUFSZ 1051. #endif 1052. static NEARDATA unsigned char inbuf[ZEROCOMP_BUFSIZ]; 1053. static NEARDATA unsigned short inbufp = 0; 1054. static NEARDATA unsigned short inbufsz = 0; 1055. static NEARDATA short inrunlength = -1; 1056. static NEARDATA int mreadfd; 1057. 1058. static int 1059. mgetc() 1060. { 1061. if (inbufp >= inbufsz) { 1062. inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf); 1063. if (!inbufsz) { 1064. if (inbufp > sizeof inbuf) 1065. error("EOF on file #%d.\n", mreadfd); 1066. inbufp = 1 + sizeof inbuf; /* exactly one warning :-) */ 1067. return -1; 1068. } 1069. inbufp = 0; 1070. } 1071. return inbuf[inbufp++]; 1072. } 1073. 1074. void 1075. minit() 1076. { 1077. inbufsz = 0; 1078. inbufp = 0; 1079. inrunlength = -1; 1080. } 1081. 1082. int 1083. mread(fd, buf, len) 1084. int fd; 1085. genericptr_t buf; 1086. register unsigned len; 1087. { 1088. /*register int readlen = 0;*/ 1089. if (fd < 0) error("Restore error; mread attempting to read file %d.", fd); 1090. mreadfd = fd; 1091. while (len--) { 1092. if (inrunlength > 0) { 1093. inrunlength--; 1094. *(*((char **)&buf))++ = '\0'; 1095. } else { 1096. register short ch = mgetc(); 1097. if (ch < 0) return -1; /*readlen;*/ 1098. if ((*(*(char **)&buf)++ = (char)ch) == RLESC) { 1099. inrunlength = mgetc(); 1100. } 1101. } 1102. /*readlen++;*/ 1103. } 1104. return 0; /*readlen;*/ 1105. } 1106. 1107. #else /* ZEROCOMP */ 1108. 1109. void 1110. minit() 1111. { 1112. return; 1113. } 1114. 1115. void 1116. mread(fd, buf, len) 1117. register int fd; 1118. register genericptr_t buf; 1119. register unsigned int len; 1120. { 1121. register int rlen; 1122. 1123. #if defined(BSD) || defined(ULTRIX) 1124. rlen = read(fd, buf, (int) len); 1125. if(rlen != len){ 1126. #else /* e.g. SYSV, __TURBOC__ */ 1127. rlen = read(fd, buf, (unsigned) len); 1128. if((unsigned)rlen != len){ 1129. #endif 1130. pline("Read %d instead of %u bytes.", rlen, len); 1131. if(restoring) { 1132. (void) close(fd); 1133. (void) delete_savefile(); 1134. error("Error restoring old game."); 1135. } 1136. panic("Error reading level file."); 1137. } 1138. } 1139. #endif /* ZEROCOMP */ 1140. 1141. /*restore.c*/