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