abstract
| - 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 [[SLASH'EM 0.0.7E7F2/restore.c#line123]], for example. The latest source code for vanilla NetHack is at Source code. 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 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.
", 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*/
|