Source:NetHack 3.2.0/restore.c

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