Source:NetHack 3.1.0/restore.c

Below is the full text to restore.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	93/01/23	*/ 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 ZEROCOMP 14.  static int NDECL(mgetc); 15.  #endif 16.  static void NDECL(find_lev_obj); 17.  #ifndef NO_SIGNAL 18.  static void NDECL(inven_inuse); 19.  #endif 20.  static void FDECL(restlevchn, (int)); 21.  static void FDECL(restdamage, (int,BOOLEAN_P)); 22.  static struct obj * FDECL(restobjchn, (int,BOOLEAN_P)); 23.  static struct monst * FDECL(restmonchn, (int,BOOLEAN_P)); 24.  static void FDECL(restgenoinfo, (int)); 25.  static boolean FDECL(restgamestate, (int, unsigned int *)); 26.  static int FDECL(restlevelfile, (int,XCHAR_P)); 27.   28.   #ifdef MULDGN 29.  #include "quest.h"  30. #endif 31.   32.   boolean restoring = FALSE; 33.  #ifdef TUTTI_FRUTTI 34.  static struct fruit NEARDATA *oldfruit; 35.  #endif 36.  static long NEARDATA omoves; 37.   38.   /* Recalculate level.objects[x][y], since this info was not saved. */ 39.   static void 40.  find_lev_obj 41.  {  42.   	register struct obj *fobjtmp = (struct obj *)0; 43.  	register struct obj *otmp; 44.  	int x,y; 45.   46.   	for(x=0; xnobj; 54.  		otmp->nobj = fobjtmp; 55.  		fobjtmp = otmp; 56.  	}  57.   	/* Set level.objects (as well as reversing the chain back again) */ 58.  	while ((otmp = fobjtmp) != 0) { 59.  		place_object(otmp, otmp->ox, otmp->oy); 60.  		fobjtmp = otmp->nobj; 61.  		otmp->nobj = fobj; 62.  		fobj = otmp; 63.  	}  64.   }  65.    66.   #ifndef NO_SIGNAL 67.  static void 68.  inven_inuse 69.  /* Things that were marked "in_use" when the game was saved (ex. via the  70.    * infamous "HUP" cheat) get used up here. 71.   */  72.   {  73.   	register struct obj *otmp, *otmp2; 74.   75.   	for(otmp = invent; otmp; otmp = otmp2) { 76.  		otmp2 = otmp->nobj; 77.  		if(otmp->in_use) { 78.  			/* in_use and oldcorpse share a bit, but we don't  79. * want nasty messages for old corpses -- 80.  			 * remove_cadavers will clean them up nicely 81.  			 */  82.   			if (otmp->otyp == CORPSE &&  83.   					mons[otmp->corpsenm].mlet == S_TROLL) 84.  				continue; 85.  			pline("Finishing off %s...", xname(otmp)); 86.  			useup(otmp); 87.  		}  88.   	}  89.   }  90.   #endif 91.   92.   static void 93.  restlevchn(fd) 94.  register int fd; 95.  {  96.   	int cnt; 97.  	s_level	*tmplev, *x; 98.   99.   	sp_levchn = (s_level *) 0; 100. 	mread(fd, (genericptr_t) &cnt, sizeof(int)); 101. 	for(cnt > 0; cnt--) { 102.  103.  	    tmplev = (s_level *)alloc(sizeof(s_level)); 104. 	    mread(fd, (genericptr_t) tmplev, sizeof(s_level)); 105. 	    if(!sp_levchn) sp_levchn = tmplev; 106. 	    else { 107.  108.  		for(x = sp_levchn; x->next; x = x->next); 109. 		x->next = tmplev; 110. 	    }  111.  	    tmplev->next = (s_level *)0; 112. 	}  113.  }  114.   115.  static void 116. restdamage(fd, ghostly) 117. int fd; 118. boolean ghostly; 119. {  120.  	int counter; 121. 	struct damage *tmp_dam; 122.  123.  	mread(fd, (genericptr_t) &counter, sizeof(counter)); 124. 	if (!counter) 125. 	    return; 126. 	tmp_dam = (struct damage *)alloc(sizeof(struct damage)); 127. 	while (1) { 128. 	    char damaged_shops[5], *shp = NULL; 129.  130.  	    mread(fd, (genericptr_t) tmp_dam, sizeof(*tmp_dam)); 131. 	    if (ghostly) 132. 		tmp_dam->when += (monstermoves - omoves); 133. 	    Strcpy(damaged_shops,  134.  		   in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE)); 135. 	    if (u.uz.dlevel) { 136. 		/* when restoring, there are two passes over the current 137. 		 * level. the first time, u.uz isn't set, so neither is 138. * shop_keeper. just wait and process the damage on 139. * the second pass. 140. 		 */  141.  		for (shp = damaged_shops; *shp; shp++) { 142. 		    struct monst *shkp = shop_keeper(*shp); 143.  144.  		    if (shkp && inhishop(shkp) && repair_damage(shkp, tmp_dam)) 145. 			break; 146. 		}  147.  	    }  148.  	    if (!shp || !*shp) { 149. 		tmp_dam->next = level.damagelist; 150. 		level.damagelist = tmp_dam; 151. 		tmp_dam = (struct damage *)alloc(sizeof(*tmp_dam)); 152. 	    }  153.  	    if (!(--counter)) { 154. 		free((genericptr_t)tmp_dam); 155. 		return; 156. 	    }  157.  	}  158.  }  159.   160.  static struct obj * 161. restobjchn(fd, ghostly) 162. register int fd; 163. boolean ghostly; 164. {  165.  	register struct obj *otmp, *otmp2; 166. 	register struct obj *first = (struct obj *)0; 167. #ifdef TUTTI_FRUTTI 168. 	register struct fruit *oldf; 169. #endif 170. 	int xl; 171.  172.  #if defined(LINT) || defined(GCC_WARN) 173. 	/* suppress "used before set" warning from lint */ 174. 	otmp2 = 0; 175. #endif 176. 	while(1) { 177. 		mread(fd, (genericptr_t) &xl, sizeof(xl)); 178. 		if(xl == -1) break; 179. 		otmp = newobj(xl); 180. 		if(!first) first = otmp; 181. 		else otmp2->nobj = otmp; 182. 		mread(fd, (genericptr_t) otmp,  183.  					(unsigned) xl + sizeof(struct obj)); 184. 		if(!otmp->o_id) otmp->o_id = flags.ident++; 185. #ifdef TUTTI_FRUTTI 186. 		if(ghostly && otmp->otyp == SLIME_MOLD) { 187. 			for(oldf=oldfruit; oldf; oldf=oldf->nextf) 188. 				if (oldf->fid == otmp->spe) break; 189. 			if(!oldf) impossible("no old fruit?"); 190. 			else otmp->spe = fruitadd(oldf->fname); 191. 		}  192.  #endif 193. 		/* Ghost levels get object age shifted from old player's clock 194. 		 * to new player's clock. Assumption: new player arrived 195. 		 * immediately after old player died. 196. 		 */  197.  		if (ghostly && otmp->otyp != OIL_LAMP  198.  				&& otmp->otyp != BRASS_LANTERN  199.  				&& otmp->otyp != CANDELABRUM_OF_INVOCATION  200.  				&& !Is_candle(otmp)) 201. 			otmp->age = monstermoves-omoves+otmp->age; 202.  203.  		/* get contents of the container */ 204. 		if (Is_container(otmp) || otmp->otyp == STATUE) 205. 		    otmp->cobj = restobjchn(fd,ghostly); 206.  207.  		otmp2 = otmp; 208. 	}  209.  	if(first && otmp2->nobj){ 210. 		impossible("Restobjchn: error reading objchn."); 211. 		otmp2->nobj = 0; 212. 	}  213.   214.  	return(first); 215. }  216.   217.  static struct monst * 218. restmonchn(fd, ghostly) 219. register int fd; 220. boolean ghostly; 221. {  222.  	register struct monst *mtmp, *mtmp2; 223. 	register struct monst *first = (struct monst *)0; 224. 	int xl; 225. 	struct permonst *monbegin; 226. 	boolean moved; 227.  228.  	/* get the original base address */ 229. 	mread(fd, (genericptr_t)&monbegin, sizeof(monbegin)); 230. 	moved = (monbegin != mons); 231.  232.  #if defined(LINT) || defined(GCC_WARN) 233. 	/* suppress "used before set" warning from lint */ 234. 	mtmp2 = 0; 235. #endif 236. 	while(1) { 237. 		mread(fd, (genericptr_t) &xl, sizeof(xl)); 238. 		if(xl == -1) break; 239. 		mtmp = newmonst(xl); 240. 		if(!first) first = mtmp; 241. 		else mtmp2->nmon = mtmp; 242. 		mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst)); 243. 		if(!mtmp->m_id) 244. 			mtmp->m_id = flags.ident++; 245. 		if (moved && mtmp->data) { 246. 			int offset = mtmp->data - monbegin;	/*(ptrdiff_t)*/ 247. 			mtmp->data = mons + offset;  /* new permonst location */ 248. 		}  249.  		if(mtmp->minvent) 250. 			mtmp->minvent = restobjchn(fd, ghostly); 251. #ifdef MUSE 252. 		if (mtmp->mw) mtmp->mw = mtmp->minvent;	/* wield 1st obj in inventory */ 253. #endif 254. 		if (mtmp->isshk) restshk(mtmp); 255.  256.  		mtmp2 = mtmp; 257. 	}  258.  	if(first && mtmp2->nmon){ 259. 		impossible("Restmonchn: error reading monchn."); 260. 		mtmp2->nmon = 0; 261. 	}  262.  	return(first); 263. }  264.   265.  static void 266. restgenoinfo(fd) 267. register int fd; 268. {  269.  	register int i;  270. unsigned genolist[NUMMONS]; 271.  272.  	mread(fd, (genericptr_t) genolist, sizeof(genolist)); 273.  274.  	for (i = 0; i < NUMMONS; i++) 275. 		mons[i].geno = genolist[i]; 276. }  277.   278.  static 279. boolean 280. restgamestate(fd, mid) 281. register int fd; 282. unsigned int *mid; 283. {  284.  	struct obj *otmp; 285. 	int tmp;		/* not a register ! */ 286.  	struct flag oldflags; 287. #ifdef TUTTI_FRUTTI 288. 	struct fruit *fruit; 289. #endif 290.  291.  	invent = restobjchn(fd, FALSE); 292. 	migrating_objs = restobjchn(fd, FALSE); 293. 	migrating_mons = restmonchn(fd, FALSE); 294. 	restgenoinfo(fd); 295.  296.  	mread(fd, (genericptr_t) &tmp, sizeof tmp); 297. #ifdef WIZARD 298. 	if(!wizard) 299. #endif 300. 	    if(tmp != getuid) {		/* strange ... */ 301.  		pline("Saved game was not yours."); 302. 		return(FALSE); 303. 	    }  304.   305.  	oldflags = flags; 306. 	mread(fd, (genericptr_t) &flags, sizeof(struct flag)); 307. 	/* Some config file and command line OPTIONS take precedence over 308. 	 * those in save file. 309. 	 */  310.  #ifdef TERMLIB 311. 	flags.DECgraphics = oldflags.DECgraphics; 312. #endif 313. #ifdef ASCIIGRAPH 314. 	flags.IBMgraphics = oldflags.IBMgraphics; 315. #endif 316. #ifdef MICRO 317. 	flags.rawio = oldflags.rawio; 318. 	flags.BIOS = oldflags.BIOS; 319. #endif 320. #ifdef TEXTCOLOR 321. 	flags.use_color = oldflags.use_color; 322. 	flags.hilite_pet = oldflags.hilite_pet; 323. #endif 324. #ifdef MAC_GRAPHICS_ENV 325. 	flags.MACgraphics = oldflags.MACgraphics; 326. 	flags.large_font = oldflags.large_font; 327. #endif 328. 	/* these come from the current environment; ignore saved values */ 329. 	flags.window_inited = oldflags.window_inited; 330. 	flags.msg_history = oldflags.msg_history; 331. 	flags.echo = oldflags.echo; 332. 	flags.cbreak = oldflags.cbreak; 333.  334.  	mread(fd, (genericptr_t) &u, sizeof(struct you)); 335. 	if(u.uhp <= 0) { 336. 	    You("were not healthy enough to survive restoration."); 337. 	    /* wiz1_level.dlevel is used by mklev.c to see if lots of stuff is  338. * uninitialized, so we only have to set it and not the other stuff. 339. 	     */  340.  	    wiz1_level.dlevel = 0; 341. 	    u.uz.dnum = 0; 342. 	    u.uz.dlevel = 1; 343. 	    return(FALSE); 344. 	}  345.   346.  	/* don't do this earlier to avoid complicating abort above */ 347. 	for(otmp = invent; otmp; otmp = otmp->nobj) 348. 		if(otmp->owornmask) 349. 			setworn(otmp, otmp->owornmask); 350.  351.  	restore_dungeon(fd); 352. 	mread(fd, (genericptr_t) &inv_pos, sizeof inv_pos); 353. 	restlevchn(fd); 354. 	mread(fd, (genericptr_t) &moves, sizeof moves); 355. 	mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves); 356. #ifdef MULDGN 357. 	mread(fd, (genericptr_t) &quest_status, sizeof(struct q_score)); 358. #endif 359. 	mread(fd, (genericptr_t) spl_book,  360.  				sizeof(struct spell) * (MAXSPELL + 1)); 361. 	restore_artifacts(fd); 362. 	restore_oracles(fd); 363. 	if(u.ustuck) 364. 		mread(fd, (genericptr_t) mid, sizeof (*mid)); 365. 	mread(fd, (genericptr_t) pl_character, sizeof pl_character); 366.  367.  #ifdef TUTTI_FRUTTI 368. 	mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); 369. 	mread(fd, (genericptr_t) &current_fruit, sizeof current_fruit); 370. 	ffruit = 0; 371. 	while (fruit = newfruit,  372.  	       mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),  373.  	       fruit->fid) { 374. 		fruit->nextf = ffruit; 375. 		ffruit = fruit; 376. 	}  377.  	dealloc_fruit(fruit); 378. #endif 379. 	restnames(fd); 380. 	restore_waterlevel(fd); 381. 	return(TRUE); 382. }  383.   384.  /*ARGSUSED*/	/* fd used in MFLOPPY only */ 385. static int 386. restlevelfile(fd, ltmp) 387. register int fd; 388. xchar ltmp; 389. {  390.  	register int nfd; 391.  392.  	nfd = create_levelfile(ltmp); 393.  394.  	if (nfd < 0)	panic("Cannot open temp level %d!", ltmp); 395. #ifdef MFLOPPY 396. 	if (!savelev(nfd, ltmp, COUNT_SAVE)) { 397.  398.  		/* The savelev can't proceed because the size required 399. 		 * is greater than the available disk space. 400. 		 */  401.  		pline("Not enough space on `%s' to restore your game.",  402.  			levels); 403.  404.  		/* Remove levels and bones that may have been created. 405. 		 */  406.  		(void) close(nfd); 407. 		eraseall(levels, alllevels); 408. # ifndef AMIGA 409. 		eraseall(levels, allbones); 410.  411.  		/* Perhaps the person would like to play without a  412. * RAMdisk. 413. 		 */  414.  		if (ramdisk) { 415. 			/* PlaywoRAMdisk may not return, but if it does 416. 			 * it is certain that ramdisk will be 0. 417. 			 */  418.  			playwoRAMdisk; 419. 			/* Rewind save file and try again */ 420. 			(void) lseek(fd, (off_t)0, 0); 421. 			return dorecover(fd);	/* 0 or 1 */ 422. 		} else { 423. # endif 424. 			pline("Be seeing you..."); 425. 			terminate(0); 426. # ifndef AMIGA 427. 		}  428.  # endif 429. 	}  430.  #endif 431. 	bufon(nfd); 432. 	savelev(nfd, ltmp, WRITE_SAVE | FREE_SAVE); 433. 	bclose(nfd); 434. 	return(2); 435. }  436.   437.  int 438. dorecover(fd) 439. register int fd; 440. {  441.  	unsigned int mid;		/* not a register */ 442. 	xchar ltmp; 443. 	int rtmp; 444. 	struct obj *otmp; 445.  446.  	minit;	/* ZEROCOMP */ 447. 	restoring = TRUE; 448. 	getlev(fd, 0, (xchar)0, FALSE); 449. 	if (!restgamestate(fd, &mid)) { 450. 		(void) close(fd); 451. 		(void) delete_savefile; 452. 		restoring = FALSE; 453. 		return(0); 454. 	}  455.  #ifdef INSURANCE 456. 	savestateinlock; 457. #endif 458. 	rtmp = restlevelfile(fd, ledger_no(&u.uz)); 459. 	if (rtmp < 2) return(rtmp);  /* dorecover called recursively */ 460.  461.  #ifdef MICRO 462. # ifdef AMIGA 463. 	{  464.  	extern winid WIN_BASE; 465. 	clear_nhwindow(WIN_BASE);	/* hack until there's a hook for this */ 466. 	}  467.  # else 468. 	clear_nhwindow(WIN_MAP); 469. # endif 470. 	clear_nhwindow(WIN_MESSAGE); 471. 	You("got as far as level %d in %s%s.",  472.  		depth(&u.uz), dungeons[u.uz.dnum].dname,  473.  		flags.debug ? " while in WIZARD mode" :  474.  		flags.explore ? " while in discovery mode" : ""); 475. 	curs(WIN_MAP, 1, 1); 476. 	dotcnt = 0; 477. 	putstr(WIN_MAP, 0, "Restoring:"); 478. #endif 479. 	while(1) { 480. #ifdef ZEROCOMP 481. 		if(mread(fd, (genericptr_t) &ltmp, sizeof ltmp) < 0) 482. #else 483. 		if(read(fd, (genericptr_t) &ltmp, sizeof ltmp) != sizeof ltmp) 484. #endif 485. 			break; 486. 		getlev(fd, 0, ltmp, FALSE); 487. #ifdef MICRO 488. 		curs(WIN_MAP, 11 + dotcnt++, 1); 489. 		putstr(WIN_MAP, 0, "."); 490. #endif 491. 		rtmp = restlevelfile(fd, ltmp); 492. 		if (rtmp < 2) return(rtmp);  /* dorecover called recursively */ 493. 	}  494.   495.  #ifdef BSD 496. 	(void) lseek(fd, 0L, 0); 497. #else 498. 	(void) lseek(fd, (off_t)0, 0); 499. #endif 500. 	minit;	/* ZEROCOMP */ 501. 	getlev(fd, 0, (xchar)0, FALSE); 502. 	(void) close(fd); 503.  504.  #if defined(WIZARD) || defined(EXPLORE_MODE) 505. 	if(  506.  # ifdef WIZARD  507.  	   !wizard  508.  #  ifdef EXPLORE_MODE  509.  		   &&  510.  #  endif  511.  # endif  512.  # ifdef EXPLORE_MODE  513.  		      !discover  514.  # endif  515.  				) 516. #endif 517. 		(void) delete_savefile; 518. #ifdef REINCARNATION 519. 	if (Is_rogue_level(&u.uz)) assign_rogue_graphics(TRUE); 520. #endif 521. 	if(u.ustuck) { 522. 		register struct monst *mtmp; 523.  524.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 525. 			if(mtmp->m_id == mid) goto monfnd; 526. 		panic("Cannot find the monster ustuck."); 527. 	monfnd: 528. 		u.ustuck = mtmp; 529. 	}  530.  #ifdef MFLOPPY 531. 	gameDiskPrompt; 532. #endif 533. 	max_rank_sz; /* to recompute mrank_sz (botl.c) */ 534. #ifdef POLYSELF 535. 	set_uasmon; 536. #endif 537. 	/* take care of iron ball & chain */ 538. 	for(otmp = fobj; otmp; otmp = otmp->nobj) 539. 		if(otmp->owornmask) 540. 			setworn(otmp, otmp->owornmask); 541. #ifndef NO_SIGNAL 542. 	/* in_use processing must be after: 543. 	 *    + The inventory has been read so that freeinv works. 544. 	 *    + The current level has been restored so billing information 545. 	 *	is available. 546. 	 */  547.  	inven_inuse; 548. #endif 549. #ifdef MULDGN 550. 	load_qtlist;	/* re-load the quest text info */ 551. #endif 552. 	/* Set up the vision internals, after levl[] data is loaded */ 553. 	/* but before docrt. */ 554.  	vision_reset; 555. 	vision_full_recalc = 1;	/* recompute vision (not saved) */ 556. 	docrt; 557. 	restoring = FALSE; 558. 	clear_nhwindow(WIN_MESSAGE); 559. 	return(1); 560. }  561.   562.  void 563. trickery 564. {  565.  	pline("Strange, this map is not as I remember it."); 566. 	pline("Somebody is trying some trickery here..."); 567. 	pline("This game is void."); 568. 	done(TRICKED); 569. }  570.   571.  void 572. getlev(fd, pid, lev, ghostly) 573. int fd, pid; 574. xchar lev; 575. boolean ghostly; 576. {  577.  	register struct trap *trap; 578. 	register struct monst *mtmp; 579. 	branch *br; 580. 	int hpid; 581. 	xchar dlvl; 582. 	int x, y;  583. #ifdef TOS 584. 	short tlev; 585. #endif 586.  587.  #if defined(MSDOS) || defined(OS2) 588. 	setmode(fd, O_BINARY); 589. #endif 590. #ifdef TUTTI_FRUTTI 591. 	/* Load the old fruit info. We have to do it first, so the 592. 	 * information is available when restoring the objects. 593. 	 */  594.  	if (ghostly) { 595. 		struct fruit *fruit; 596.  597.  		oldfruit = 0; 598. 		while (fruit = newfruit,  599.  		       mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),  600.  		       fruit->fid) { 601. 			fruit->nextf = oldfruit; 602. 			oldfruit = fruit; 603. 		}  604.  		dealloc_fruit(fruit); 605. 	}  606.  #endif 607.  608.  	/* First some sanity checks */ 609. 	mread(fd, (genericptr_t) &hpid, sizeof(hpid)); 610. /* CHECK:  This may prevent restoration */ 611. #ifdef TOS 612. 	mread(fd, (genericptr_t) &tlev, sizeof(tlev)); 613. 	dlvl=tlev&0x00ff; 614. #else 615. 	mread(fd, (genericptr_t) &dlvl, sizeof(dlvl)); 616. #endif 617. 	if((pid && pid != hpid) || (lev && dlvl != lev)) { 618. #ifdef WIZARD 619. 		if (wizard) { 620. 			if (pid && pid != hpid) 621. 				pline("PID (%d) doesn't match saved PID (%d)!", hpid, pid); 622. 			else if (lev && dlvl != lev) 623. 				pline("This is level %d, not %d!", dlvl, lev); 624. 		}  625.  #endif 626. 		trickery; 627. 	}  628.   629.  #ifdef RLECOMP 630. 	{  631.  		short	i, j;  632. uchar	len; 633. 		struct rm r;  634. 635. 		i = 0; j = 0; len = 0; 636. 		while(i < ROWNO) { 637. 		    while(j < COLNO) { 638. 			if(len > 0) { 639. 			    levl[j][i] = r;  640. len -= 1; 641. 			    j += 1; 642. 			} else { 643. 			    mread(fd, (genericptr_t)&len, sizeof(uchar)); 644. 			    mread(fd, (genericptr_t)&r, sizeof(struct rm)); 645. 			}  646.  		    }  647.  		    j = 0; 648. 		    i += 1; 649. 		}  650.  	}  651.  #else 652. 	mread(fd, (genericptr_t) levl, sizeof(levl)); 653. #endif	/* RLECOMP */ 654.  655.  	mread(fd, (genericptr_t)&omoves, sizeof(omoves)); 656. 	mread(fd, (genericptr_t)&upstair, sizeof(stairway)); 657. 	mread(fd, (genericptr_t)&dnstair, sizeof(stairway)); 658. 	mread(fd, (genericptr_t)&upladder, sizeof(stairway)); 659. 	mread(fd, (genericptr_t)&dnladder, sizeof(stairway)); 660. 	mread(fd, (genericptr_t)&sstairs, sizeof(stairway)); 661. 	mread(fd, (genericptr_t)&updest, sizeof(dest_area)); 662. 	mread(fd, (genericptr_t)&dndest, sizeof(dest_area)); 663. 	mread(fd, (genericptr_t)&level.flags, sizeof(level.flags)); 664.  665.  	fmon = restmonchn(fd, ghostly); 666.  667.  	/* regenerate animals while on another level */ 668. 	{ long tmoves = (monstermoves > omoves) ? monstermoves-omoves : 0; 669. 	  register struct monst *mtmp2; 670.  671.  	  for(mtmp = fmon; mtmp; mtmp = mtmp2) { 672. 		mtmp2 = mtmp->nmon; 673. 		if(mtmp->data->geno & G_GENOD) { 674. 			/* mondead would try to link the monster's objects 675. 			 * into fobj and the appropriate nexthere chain. 676. 			 * unfortunately, such things will not have sane 677. 			 * values until after find_lev_obj well below 678. 			 * here, so we'd go chasing random pointers if we  679. * tried that. we could save the monster's objects 680. 			 * in another chain and insert them in the level 681. 			 * later, but that's a lot of work for very little 682. 			 * gain. hence, just throw the objects away via 683. 			 * mongone and pretend the monster wandered off 684. 			 * somewhere private before the genocide. 685. 			 */  686.  			mongone(mtmp); 687. 			continue; 688. 		}  689.   690.  		if (ghostly) { 691. 			/* reset peaceful/malign relative to new character */ 692. 			if(!mtmp->isshk) 693. 				/* shopkeepers will reset based on name */ 694. 				mtmp->mpeaceful = peace_minded(mtmp->data); 695. 			set_malign(mtmp); 696. 		} else if (mtmp->mtame && tmoves > 250) 697. 			mtmp->mtame = mtmp->mpeaceful = 0; 698.  699.  		/* restore shape changers - Maarten Jan Huisjes */ 700. 		if (mtmp->data == &mons[PM_CHAMELEON]  701.  		    && !Protection_from_shape_changers  702.  		    && !mtmp->cham) 703. 			mtmp->cham = 1; 704. 		else if(Protection_from_shape_changers) { 705. 			if (mtmp->cham) { 706. 				mtmp->cham = 0; 707. 				(void) newcham(mtmp, &mons[PM_CHAMELEON]); 708. 			} else if(is_were(mtmp->data) && !is_human(mtmp->data)) 709. 				new_were(mtmp); 710. 		}  711.   712.  		if (!ghostly) { 713. 			long nhp = mtmp->mhp + 714. 				(regenerates(mtmp->data) ? tmoves : tmoves/20); 715.  716.  			if(!mtmp->mcansee && mtmp->mblinded) { 717. 				if ((long) mtmp->mblinded <= tmoves) { 718. 					mtmp->mblinded = 0; 719. 					mtmp->mcansee = 1; 720. 				} else mtmp->mblinded -= tmoves; 721. 			}  722.  			if(!mtmp->mcanmove && mtmp->mfrozen) { 723. 				if ((long) mtmp->mfrozen <= tmoves) { 724. 					mtmp->mfrozen = 0; 725. 					mtmp->mcanmove = 1; 726. 				} else mtmp->mfrozen -= tmoves; 727. 			}  728.  			if(mtmp->mflee && mtmp->mfleetim) { 729. 				if ((long) mtmp->mfleetim <= tmoves) { 730. 					mtmp->mfleetim = 0; 731. 					mtmp->mflee = 0; 732. 				} else mtmp->mfleetim -= tmoves; 733. 			}  734.  			if(nhp >= mtmp->mhpmax) 735. 				mtmp->mhp = mtmp->mhpmax; 736. 			else 737. 				mtmp->mhp = nhp; 738. 		}  739.  	  }  740.  	}  741.   742.  	rest_worm(fd);	/* restore worm information */ 743. 	ftrap = 0; 744. 	while (trap = newtrap,  745.  	       mread(fd, (genericptr_t)trap, sizeof(struct trap)),  746.  	       trap->tx) { 747. 		trap->ntrap = ftrap; 748. 		ftrap = trap; 749. 	}  750.  	dealloc_trap(trap); 751. 	fobj = restobjchn(fd, ghostly); 752. 	find_lev_obj; 753. 	billobjs = restobjchn(fd, ghostly); 754. 	rest_engravings(fd); 755. 	rest_rooms(fd);		/* No joke :-) */  756.  	mread(fd, (genericptr_t)doors, sizeof(doors));  757.   758.  	/* reset level.monsters for new level */  759.  	for (x = 0; x < COLNO; x++)  760.  	    for (y = 0; y < ROWNO; y++)  761.  		level.monsters[x][y] = (struct monst *) 0;  762.  	for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon) {  763.  	    if (mtmp->isshk)  764.  		set_residency(mtmp, FALSE);  765.  	    place_monster(mtmp, mtmp->mx, mtmp->my);  766.  	    if (mtmp->wormno) place_wsegs(mtmp);  767.  	}  768.  	restdamage(fd, ghostly);  769.   770.   771.  #ifdef TUTTI_FRUTTI  772.  	/* Now get rid of all the temp fruits... */  773.  	if (ghostly) {  774.  		struct fruit *fruit;  775.   776.  		while(oldfruit) {  777.  			fruit = oldfruit->nextf;  778.  			dealloc_fruit(oldfruit);  779.  			oldfruit = fruit;  780.  		}  781.  	}  782.  #endif  783.  	if (ghostly && lev > ledger_no(&medusa_level) && 784. 			lev < ledger_no(&stronghold_level) && xdnstair == 0) {  785.  		coord cc;  786.   787.  		mazexy(&cc);  788.  		xdnstair = cc.x;  789.  		ydnstair = cc.y;  790.  		levl[cc.x][cc.y].typ = STAIRS;  791.  	}  792.  	if (ghostly && (br = Is_branchlev(&u.uz)) && u.uz.dlevel == 1) {  793.  	    d_level ltmp;  794.   795.  	    if (on_level(&u.uz, &br->end1))  796.  		assign_level(&ltmp, &br->end2);  797.  	    else  798.  		assign_level(&ltmp, &br->end1);  799.   800.  	    switch(br->type) {  801.  	    case BR_STAIR:  802.  	    case BR_NO_END1:  803.  	    case BR_NO_END2: /* OK to assign to sstairs if it's not used */  804.  		assign_level(&sstairs.tolev, &ltmp);  805.  		break;		  806.  	    case BR_PORTAL: /* max of 1 portal per level */  807.  		{  808.  		    register struct trap *ttmp;  809.  		    for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)  810.  			if (ttmp->ttyp == MAGIC_PORTAL) 811. 			    break; 812. 		    if (!ttmp) panic("getlev: need portal but none found"); 813. 		    assign_level(&ttmp->dst, &ltmp); 814. 		}  815.  		break; 816. 	    }  817.  	}  818.  }  819.   820.  #ifdef ZEROCOMP 821. #define RLESC '\0'	/* Leading character for run of RLESC's */ 822.  823.  #ifndef ZEROCOMP_BUFSIZ 824. #define ZEROCOMP_BUFSIZ BUFSZ 825. #endif 826. static unsigned char NEARDATA inbuf[ZEROCOMP_BUFSIZ]; 827. static unsigned short NEARDATA inbufp = 0; 828. static unsigned short NEARDATA inbufsz = 0; 829. static short NEARDATA inrunlength = -1; 830. static int NEARDATA mreadfd; 831.  832.  static int 833. mgetc 834. {  835.      if (inbufp >= inbufsz) { 836. 	inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf); 837. 	if (!inbufsz) { 838. 	    if (inbufp > sizeof inbuf) 839. 		error("EOF on file #%d.\n", mreadfd); 840. 	    inbufp = 1 + sizeof inbuf;  /* exactly one warning :-) */  841.  	    return -1;  842.  	}  843.  	inbufp = 0;  844.      }  845.      return inbuf[inbufp++];  846.  }  847.   848.  void  849.  minit  850.  {  851.      inbufsz = 0;  852.      inbufp = 0;  853.      inrunlength = -1;  854.  }  855.   856.  int  857.  mread(fd, buf, len)  858.  int fd;  859.  genericptr_t buf;  860.  register unsigned len;  861.  {  862.      /*register int readlen = 0;*/  863.      mreadfd = fd;  864.      while (len--) {  865.  	if (inrunlength > 0) {  866.  	    inrunlength--;  867.  	    *(*((char **)&buf))++ = '\0';  868.  	} else {  869.  	    register short ch = mgetc;  870.  	    if (ch < 0) return -1; /*readlen;*/  871.  	    if ((*(*(char **)&buf)++ = ch) == RLESC) {  872.  		inrunlength = mgetc;  873.  	    }  874.  	}  875.  	/*readlen++;*/  876.      }  877.      return 0; /*readlen;*/ 878. }  879.   880.  #else /* ZEROCOMP */ 881.  882.  void 883. minit 884. {  885.      return; 886. }  887.   888.  void 889. mread(fd, buf, len) 890. register int fd; 891. register genericptr_t buf; 892. register unsigned int len; 893. {  894.  	register int rlen; 895.  896.  #if defined(BSD) || defined(ULTRIX) 897. 	rlen = read(fd, buf, (int) len); 898. 	if(rlen != len){ 899. #else /* e.g. SYSV, __TURBOC__ */ 900. 	rlen = read(fd, buf, (unsigned) len); 901. 	if((unsigned)rlen != len){ 902. #endif 903. 		pline("Read %d instead of %u bytes.", rlen, len); 904. 		if(restoring) { 905. 			(void) close(fd); 906. 			(void) delete_savefile; 907. 			error("Error restoring old game."); 908. 		}  909.  		panic("Error reading level file."); 910. 	}  911.  }  912.  #endif /* ZEROCOMP */ 913.  914.  /*restore.c*/