Source:NetHack 3.0.0/restore.c

Below is the full text to restore.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0	88/10/25 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. 8.   #ifdef WORM 9.   #include "wseg.h"  10. #endif 11.   12.   boolean restoring = FALSE; 13.  static struct fruit *oldfruit; 14.  static long omoves; 15.   16.   /*  17.    * "stuff" objects back into containers (relink the fcobj list). 18.   */  19.   static void 20.  stuff_objs(cobj) 21.  register struct obj *cobj; 22.  {  23.   	register struct obj *otmp, *otmp2; 24.   25.   	for(cobj; cobj = cobj->nobj) 26.  	    if(Is_container(cobj)) 27.   28.   		for(otmp = cobj->nobj;  29.   		    otmp && otmp->cobj == (struct obj *) -1; otmp = otmp2) { 30.   31.   		    otmp2 = otmp->nobj; 32.   33.   		    otmp->cobj = cobj; 34.  		    cobj->nobj = otmp2; 35.  		    otmp->nobj = fcobj; 36.  		    fcobj = otmp; 37.  		}  38.   }  39.    40.   static struct obj * 41.  restobjchn(fd, ghostly) 42.  register int fd; 43.  boolean ghostly; 44.  {  45.   	register struct obj *otmp, *otmp2; 46.  	register struct obj *first = 0; 47.  	register struct fruit *oldf; 48.  	int xl; 49.  #ifdef LINT 50.  	/* suppress "used before set" warning from lint */ 51.  	otmp2 = 0; 52.  #endif 53.  	while(1) { 54.  		mread(fd, (genericptr_t) &xl, sizeof(xl)); 55.  		if(xl == -1) break; 56.  		otmp = newobj(xl); 57.  		if(!first) first = otmp; 58.  		else otmp2->nobj = otmp; 59.  		mread(fd, (genericptr_t) otmp, (unsigned) xl + sizeof(struct obj)); 60.  		if(!otmp->o_id) otmp->o_id = flags.ident++; 61.  		if(ghostly && otmp->otyp == SLIME_MOLD) { 62.  			for(oldf=oldfruit; oldf; oldf=oldf->nextf) 63.  				if (oldf->fid == otmp->spe) break; 64.  			if(!oldf) impossible("no old fruit?"); 65.  			else otmp->spe = fruitadd(oldf->fname); 66.  		}  67.   	/* Ghost levels get object age shifted from old player's clock to  68. * new player's clock. Assumption: new player arrived immediately 69.  	 * after old player died. 70.  	 */  71.   		if (ghostly) otmp->age = moves-omoves+otmp->age; 72.  		otmp2 = otmp; 73.  	}  74.   	if(first && otmp2->nobj){ 75.  		impossible("Restobjchn: error reading objchn."); 76.  		otmp2->nobj = 0; 77.  	}  78.    79.   	stuff_objs(first); 80.  	return(first); 81.  }  82.    83.   static struct monst * 84.  restmonchn(fd, ghostly) 85.  register int fd; 86.  boolean ghostly; 87.  {  88.   	register struct monst *mtmp, *mtmp2; 89.  	register struct monst *first = 0; 90.  	int xl; 91.   92.   	struct permonst *monbegin; 93.  	off_t differ; 94.   95.   	mread(fd, (genericptr_t)&monbegin, sizeof(monbegin)); 96.  #ifndef MSDOS 97.  	differ = (genericptr_t)(&mons[0]) - (genericptr_t)(monbegin); 98.  #else 99.  	differ = (long)(&mons[0]) - (long)(monbegin); 100. #endif 101.  102.  #ifdef LINT 103. 	/* suppress "used before set" warning from lint */ 104. 	mtmp2 = 0; 105. #endif 106. 	while(1) { 107. 		mread(fd, (genericptr_t) &xl, sizeof(xl)); 108. 		if(xl == -1) break; 109. 		mtmp = newmonst(xl); 110. 		if(!first) first = mtmp; 111. 		else mtmp2->nmon = mtmp; 112. 		mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst)); 113. 		if(!mtmp->m_id) 114. 			mtmp->m_id = flags.ident++; 115. #ifndef MSDOS 116. 		/*ANSI type for differ is ptrdiff_t - long may be wrong*/ 117. 		/*for segmented architecture - may be better to cast pointers*/ 118. 		/*to (struct permonst *) rather than (genericptr_t)*/ 119. 		/*this code handles save file -  so any bug should glow*/ 120. 		/*probably best not to keep lint from complaining*/ 121. /*#ifdef LINT	/*possible compiler/hardware dependency - */ 122. /*		if (differ) mtmp->data = NULL;*/ 123. /*#else*/ 124. 		mtmp->data = (struct permonst *) 125. 			((genericptr_t)mtmp->data + differ); 126. /*#endif	/*LINT*/ 127. #else 128. 		mtmp->data = (struct permonst *) 129. 			((long) mtmp->data + differ); 130. #endif 131. 		if(mtmp->minvent) 132. 			mtmp->minvent = restobjchn(fd, ghostly); 133. 		mtmp2 = mtmp; 134. 	}  135.  	if(first && mtmp2->nmon){ 136. 		impossible("Restmonchn: error reading monchn."); 137. 		mtmp2->nmon = 0; 138. 	}  139.  	return(first); 140. }  141.   142.  static void 143. restgenoinfo(fd) 144. register int fd; 145. {  146.  	register int i;  147. 148. 	for (i = 0; i < NUMMONS; i++) 149. 		mread(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned)); 150. }  151.   152.  int 153. dorecover(fd) 154. register int fd; 155. {  156.  	register int nfd; 157. 	int tmp;		/* not a register ! */ 158.  	xchar ltmp; 159. 	unsigned int mid;		/* idem */ 160. 	struct obj *otmp; 161. 	struct fruit *fruit; 162. #ifdef MSDOS 163. 	struct flag oldflags; 164.  165.  	oldflags = flags;	/* Save flags set in the config file */ 166. #endif 167. #ifdef ZEROCOMP 168. 	minit; 169. #endif 170. 	restoring = TRUE; 171. 	getlev(fd, 0, (xchar)0, FALSE); 172. 	invent = restobjchn(fd, FALSE); 173. 	for(otmp = invent; otmp; otmp = otmp->nobj) 174. 		if(otmp->owornmask) 175. 			setworn(otmp, otmp->owornmask); 176. 	fallen_down = restmonchn(fd, FALSE); 177. 	restgenoinfo(fd); 178. 	mread(fd, (genericptr_t) &tmp, sizeof tmp); 179. #ifdef WIZARD 180. 	if(!wizard) 181. #endif 182. 	    if(tmp != getuid) {		/* strange ... */ 183.  		(void) close(fd); 184. 		(void) unlink(SAVEF); 185. 		(void) puts("Saved game was not yours."); 186. 		restoring = FALSE; 187. 		return(0); 188. 	    }  189.  	mread(fd, (genericptr_t) &flags, sizeof(struct flag)); 190. 	/* Some config file OPTIONS take precedence over those in save file. 191. 	 */  192.  #ifdef MSDOS 193. #ifdef DGK 194. 	flags.rawio = oldflags.rawio; 195. #ifdef DECRAINBOW 196. 	flags.DECRainbow = oldflags.DECRainbow; 197. #endif /* DECRAINBOW */ 198. 	flags.IBMBIOS = oldflags.IBMBIOS; 199. #endif 200. #endif 201. 	mread(fd, (genericptr_t) &dlevel, sizeof dlevel); 202. 	mread(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel); 203. 	mread(fd, (genericptr_t) &moves, sizeof moves); 204. 	mread(fd, (genericptr_t) &wiz_level, sizeof wiz_level); 205. 	mread(fd, (genericptr_t) &medusa_level, sizeof medusa_level); 206. #ifdef ORACLE 207. 	mread(fd, (genericptr_t) &oracle_level, sizeof oracle_level); 208. #endif 209. #ifdef REINCARNATION 210. 	mread(fd, (genericptr_t) &rogue_level, sizeof rogue_level); 211. 	if (dlevel==rogue_level) 212. 		savesyms = showsyms; 213. #endif 214. #ifdef STRONGHOLD 215. 	mread(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level); 216. 	mread(fd, (genericptr_t) &tower_level, sizeof tower_level); 217. 	mread(fd, (genericptr_t) tune, sizeof tune); 218. #  ifdef MUSIC 219. 	mread(fd, (genericptr_t) &music_heard, sizeof music_heard); 220. #  endif 221. #endif 222. 	mread(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev); 223. 	mread(fd, (genericptr_t) &u, sizeof(struct you)); 224. #ifdef SPELLS 225. 	mread(fd, (genericptr_t) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); 226. #endif 227. 	if(u.ustuck) 228. 		mread(fd, (genericptr_t) &mid, sizeof mid); 229. 	mread(fd, (genericptr_t) pl_character, sizeof pl_character); 230. 	mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); 231. 	mread(fd, (genericptr_t) &current_fruit, sizeof current_fruit); 232. 	ffruit = 0; 233. 	while (fruit = newfruit,  234.  	       mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),  235.  	       fruit->fid) { 236. 		fruit->nextf = ffruit; 237. 		ffruit = fruit; 238. 	}  239.  	free((genericptr_t) fruit); 240.  241.  	restnames(fd); 242. #ifdef DGK 243. 	msmsg("\n"); 244. 	cl_end; 245. 	msmsg("You got as far as level %d%s.\n", maxdlevel,  246.  		flags.debug ? " in WIZARD mode" :  247.  		flags.explore ? " in discovery mode" : ""); 248. 	cl_end; 249. 	msmsg("Restoring: "); 250. #endif 251. 	while(1) { 252. #ifdef ZEROCOMP 253. 		if(mread(fd, (genericptr_t) &ltmp, sizeof ltmp) < 0) 254. #else 255. 		if(read(fd, (genericptr_t) &ltmp, sizeof ltmp) != sizeof ltmp) 256. #endif 257. 			break; 258. 		getlev(fd, 0, ltmp, FALSE); 259. 		glo(ltmp); 260. #ifdef DGK 261. 		msmsg("."); 262. #endif 263. #if defined(MSDOS) && !defined(TOS) 264. 		nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); 265. #else 266. 		nfd = creat(lock, FCMASK); 267. #endif 268. 		if (nfd < 0)	panic("Cannot open temp file %s!\n", lock); 269. #if defined(DGK) && !defined(TOS) 270. 		if (!savelev(nfd, ltmp, COUNT | WRITE)) { 271.  272.  			/* The savelev can't proceed because the size required 273. 			 * is greater than the available disk space. 274. 			 */  275.  			msmsg("\nNot enough space on `%s' to restore your game.\n",  276.  				levels); 277.  278.  			/* Remove levels and bones that may have been created. 279. 			 */  280.  			(void) close(nfd); 281. 			eraseall(levels, alllevels); 282. 			eraseall(levels, allbones); 283.  284.  			/* Perhaps the person would like to play without a  285. * RAMdisk. 286. 			 */  287.  			if (ramdisk) { 288. 				/* PlaywoRAMdisk may not return, but if it does 289. 				 * it is certain that ramdisk will be 0. 290. 				 */  291.  				playwoRAMdisk; 292. 				/* Rewind save file and try again */ 293. 				(void) lseek(fd, (off_t)0, 0); 294. 				return dorecover(fd); 295. 			} else { 296. 				msmsg("Be seeing you...\n"); 297. 				exit(0); 298. 			}  299.  		}  300.  #else 301. 		savelev(nfd, ltmp); 302. #endif 303. #ifdef ZEROCOMP 304. 		bflush(nfd); 305. #endif 306. 		(void) close(nfd); 307. 	}  308.  #ifdef BSD 309. 	(void) lseek(fd, 0L, 0); 310. #else 311. 	(void) lseek(fd, (off_t)0, 0); 312. #endif 313. #ifdef ZEROCOMP 314. 	minit; 315. #endif 316. 	getlev(fd, 0, (xchar)0, FALSE); 317. 	(void) close(fd); 318. #ifdef EXPLORE_MODE 319. 	if(!discover) 320. #endif 321. 		(void) unlink(SAVEF); 322. #ifdef REINCARNATION 323. 	/* this can't be done earlier because we need to check the initial 324. 	 * showsyms against the one saved in each of the non-rogue levels */ 325. 	if (dlevel==rogue_level) 326. 		showsyms = defsyms; 327. #endif 328. 	if(u.ustuck) { 329. 		register struct monst *mtmp; 330.  331.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 332. 			if(mtmp->m_id == mid) goto monfnd; 333. 		panic("Cannot find the monster ustuck."); 334. 	monfnd: 335. 		u.ustuck = mtmp; 336. 	}  337.  	setsee;  /* only to recompute seelx etc. - these weren't saved */ 338. #ifdef DGK 339. 	gameDiskPrompt; 340. #endif 341. 	max_rank_sz; /* to recompute mrank_sz (pri.c) */ 342. #ifdef POLYSELF 343. 	set_uasmon; 344. #endif 345. 	/* take care of iron ball & chain */ 346. 	for(otmp = fobj; otmp; otmp = otmp->nobj) 347. 		if(otmp->owornmask) 348. 			setworn(otmp, otmp->owornmask); 349. 	docrt; 350. 	restoring = FALSE; 351. 	return(1); 352. }  353.   354.  void 355. getlev(fd, pid, lev, ghostly) 356. int fd, pid; 357. xchar lev; 358. boolean ghostly; 359. {  360.  	register struct gold *gold; 361. 	register struct trap *trap; 362. #ifdef WORM 363. 	register struct wseg *wtmp; 364. 	register int tmp; 365. #endif 366. 	long nhp; 367. 	int hpid; 368. 	xchar dlvl; 369. 	struct symbols osymbol; 370. 	int x, y;  371. uchar osym, nsym; 372. #ifdef TOS 373. 	short tlev; 374. #endif 375.  376.  #ifdef MSDOS 377. 	setmode(fd, O_BINARY);	    /* is this required for TOS??? */ 378.  #endif 379. 	/* Load the old fruit info. We have to do it first, so the infor- 380. 	 * mation is available when restoring the objects. 381. 	 */  382.  	if (ghostly) { 383. 		struct fruit *fruit; 384.  385.  		oldfruit = 0; 386. 		while (fruit = newfruit,  387.  		       mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),  388.  		       fruit->fid) { 389. 			fruit->nextf = oldfruit; 390. 			oldfruit = fruit; 391. 		}  392.  		free((genericptr_t) fruit); 393. 	}  394.   395.  	/* First some sanity checks */ 396. 	mread(fd, (genericptr_t) &hpid, sizeof(hpid)); 397. #ifdef TOS 398. 	mread(fd, (genericptr_t) &tlev, sizeof(tlev)); 399. 	dlvl=tlev&0xff; 400. #else 401. 	mread(fd, (genericptr_t) &dlvl, sizeof(dlvl)); 402. #endif 403. 	if((pid && pid != hpid) || (lev && dlvl != lev)) { 404. 		pline("Strange, this map is not as I remember it."); 405. 		pline("Somebody is trying some trickery here..."); 406. 		pline("This game is void."); 407. 		done("tricked"); 408. 	}  409.   410.  	mread(fd, (genericptr_t) levl, sizeof(levl)); 411. 	mread(fd, (genericptr_t) &osymbol, sizeof(osymbol)); 412. 	if (memcmp((genericptr_t) &osymbol, 413. 		   (genericptr_t) &showsyms, sizeof (struct symbols))  414.  #ifdef REINCARNATION  415.  		&& dlvl != rogue_level  416.  		/* rogue level always uses default syms, and showsyms will still  417.  		 * have its initial value from environment when restoring a  418.  		 * game */  419.  #endif  420.  	    ) { 421. 		for (x = 0; x < COLNO; x++) 422. 			for (y = 0; y < ROWNO; y++) { 423. 				osym = levl[x][y].scrsym; 424. 				nsym = 0; 425. 				switch (levl[x][y].typ) { 426. 				case STONE: 427. 				case SCORR: 428. 					if (osym == osymbol.stone) 429. 						nsym = showsyms.stone; 430. 					break; 431. 				case ROOM: 432. #ifdef STRONGHOLD 433. 				case DRAWBRIDGE_DOWN: 434. #endif /* STRONGHOLD /**/ 435. 					if (osym == osymbol.room) 436. 						nsym = showsyms.room; 437. 					break; 438. 				case DOOR: 439. 					if (osym == osymbol.door) 440. 						nsym = showsyms.door; 441. 					break; 442. 				case CORR: 443. 					if (osym == osymbol.corr) 444. 						nsym = showsyms.corr; 445. 					break; 446. 				case VWALL: 447. 					if (osym == osymbol.vwall) 448. 						nsym = showsyms.vwall; 449. #ifdef STRONGHOLD 450. 					else if (osym == osymbol.dbvwall) 451. 						nsym = showsyms.dbvwall; 452. #endif 453. 					break; 454. 				case HWALL: 455. 					if (osym == osymbol.hwall) 456. 						nsym = showsyms.hwall; 457. #ifdef STRONGHOLD 458. 					else if (osym == osymbol.dbhwall) 459. 						nsym = showsyms.dbhwall; 460. #endif 461. 					break; 462. 				case TLCORNER: 463. 					if (osym == osymbol.tlcorn) 464. 						nsym = showsyms.tlcorn; 465. 					break; 466. 				case TRCORNER: 467. 					if (osym == osymbol.trcorn) 468. 						nsym = showsyms.trcorn; 469. 					break; 470. 				case BLCORNER: 471. 					if (osym == osymbol.blcorn) 472. 						nsym = showsyms.blcorn; 473. 					break; 474. 				case BRCORNER: 475. 					if (osym == osymbol.brcorn) 476. 						nsym = showsyms.brcorn; 477. 					break; 478. 				case SDOOR: 479. 					if (osym == osymbol.vwall) 480. 						nsym = showsyms.vwall; 481. 					else if (osym == osymbol.hwall) 482. 						nsym = showsyms.hwall; 483. 					break; 484. 				case CROSSWALL: 485. 					if (osym == osymbol.crwall) 486. 						nsym = showsyms.crwall; 487. 					break; 488. 				case TUWALL: 489. 					if (osym == osymbol.tuwall) 490. 						nsym = showsyms.tuwall; 491. 					break; 492. 				case TDWALL: 493. 					if (osym == osymbol.tdwall) 494. 						nsym = showsyms.tdwall; 495. 					break; 496. 				case TLWALL: 497. 					if (osym == osymbol.tlwall) 498. 						nsym = showsyms.tlwall; 499. 					break; 500. 				case TRWALL: 501. 					if (osym == osymbol.trwall) 502. 						nsym = showsyms.trwall; 503. 					break; 504. 				case STAIRS: 505. 					if (osym == osymbol.upstair) 506. 						nsym = showsyms.upstair; 507. 					else if (osym == osymbol.dnstair) 508. 						nsym = showsyms.dnstair; 509. 					break; 510. #ifdef STRONGHOLD 511. 				case LADDER: 512. 					if (osym == osymbol.upladder) 513. 						nsym = showsyms.upladder; 514. 					else if (osym == osymbol.dnladder) 515. 						nsym = showsyms.dnladder; 516. 					break; 517. #endif /* STRONGHOLD /**/ 518. 				case POOL: 519. 				case MOAT: 520. #ifdef STRONGHOLD 521. 				case DRAWBRIDGE_UP: 522. #endif /* STRONGHOLD /**/ 523. 					if (osym == osymbol.pool) 524. 						nsym = showsyms.pool; 525. 					break; 526. #ifdef FOUNTAINS 527. 				case FOUNTAIN: 528. 					if (osym == osymbol.fountain) 529. 						nsym = showsyms.fountain; 530. 					break; 531. #endif /* FOUNTAINS /**/ 532. #ifdef THRONES 533. 				case THRONE: 534. 					if (osym == osymbol.throne) 535. 						nsym = showsyms.throne; 536. 					break; 537. #endif /* THRONES /**/ 538. #ifdef SINKS 539. 				case SINK: 540. 					if (osym == osymbol.sink) 541. 						nsym = showsyms.sink; 542. 					break; 543. #endif /* SINKS /**/ 544. #ifdef ALTARS 545. 				case ALTAR: 546. 					if (osym == osymbol.altar) 547. 						nsym = showsyms.altar; 548. 					break; 549. #endif /* ALTARS /**/ 550. 				default: 551. 					break; 552. 				}  553.  				if (nsym) 554. 					levl[x][y].scrsym = nsym; 555. 			}  556.  	}  557.   558.  	mread(fd, (genericptr_t)&omoves, sizeof(omoves)); 559. 	mread(fd, (genericptr_t)&xupstair, sizeof(xupstair)); 560. 	mread(fd, (genericptr_t)&yupstair, sizeof(yupstair)); 561. 	mread(fd, (genericptr_t)&xdnstair, sizeof(xdnstair)); 562. 	mread(fd, (genericptr_t)&ydnstair, sizeof(ydnstair)); 563. #ifdef STRONGHOLD 564. 	mread(fd, (genericptr_t)&xupladder, sizeof(xupladder)); 565. 	mread(fd, (genericptr_t)&yupladder, sizeof(yupladder)); 566. 	mread(fd, (genericptr_t)&xdnladder, sizeof(xdnladder)); 567. 	mread(fd, (genericptr_t)&ydnladder, sizeof(ydnladder)); 568. #endif 569. 	mread(fd, (genericptr_t)&fountsound, sizeof(fountsound)); 570. 	mread(fd, (genericptr_t)&sinksound, sizeof(sinksound)); 571. 	fmon = restmonchn(fd, ghostly); 572.  573.  	/* regenerate animals while on another level */ 574. 	{ long tmoves = (moves > omoves) ? moves-omoves : 0; 575. 	  register struct monst *mtmp, *mtmp2; 576.  577.  	  for(mtmp = fmon; mtmp; mtmp = mtmp2) { 578.  579.  		mtmp2 = mtmp->nmon; 580. 		if(mtmp->data->geno & G_GENOD) { 581. 			mondead(mtmp); 582. 			continue; 583. 		}  584.   585.  		if (ghostly) { 586. 			/* reset peaceful/malign relative to new character */ 587. 			if(!mtmp->isshk) 588. 				/* shopkeepers will reset based on name */ 589. 				mtmp->mpeaceful = peace_minded(mtmp->data); 590. 			set_malign(mtmp); 591. 		} else if (mtmp->mtame && tmoves > 250) 592. 		  	mtmp->mtame = mtmp->mpeaceful = 0; 593.  594.  		/* restore shape changers - Maarten Jan Huisjes */ 595. 		if (mtmp->data == &mons[PM_CHAMELEON]  596.  		    && !Protection_from_shape_changers  597.  		    && !mtmp->cham) 598. 			mtmp->cham = 1; 599. 		else if(Protection_from_shape_changers) { 600. 			if (mtmp->cham) { 601. 				mtmp->cham = 0; 602. 				(void) newcham(mtmp, &mons[PM_CHAMELEON]); 603. 			} else if(is_were(mtmp->data) && !is_human(mtmp->data)) 604. 				(void) new_were(mtmp); 605. 		}  606.   607.  		if (!ghostly) { 608. 			nhp = mtmp->mhp + 609. 				(regenerates(mtmp->data) ? tmoves : tmoves/20); 610. 			if(nhp > mtmp->mhpmax) 611. 				mtmp->mhp = mtmp->mhpmax; 612. 			else 613. #ifdef LINT	/* (long)newhp -> (schar = short int) mhp; ok in context of text above */ 614. 				mtmp->mhp = 0; 615. #else 616. 				mtmp->mhp = nhp; 617. #endif 618. 		}  619.  	  }  620.  	}  621.   622.  	setgd; 623. 	fgold = 0; 624. 	while(gold = newgold,  625.  	      mread(fd, (genericptr_t)gold, sizeof(struct gold)),  626.  	      gold->gx) { 627. 		gold->ngold = fgold; 628. 		fgold = gold; 629. 	}  630.  	free((genericptr_t) gold); 631. 	ftrap = 0; 632. 	while (trap = newtrap,  633.  	       mread(fd, (genericptr_t)trap, sizeof(struct trap)),  634.  	       trap->tx) { 635. 		trap->ntrap = ftrap; 636. 		ftrap = trap; 637. 	}  638.  	free((genericptr_t) trap); 639. 	fobj = restobjchn(fd, ghostly); 640. 	billobjs = restobjchn(fd, ghostly); 641. 	rest_engravings(fd); 642. 	mread(fd, (genericptr_t)rooms, sizeof(rooms)); 643. 	mread(fd, (genericptr_t)doors, sizeof(doors)); 644. #ifdef WORM 645. 	mread(fd, (genericptr_t)wsegs, sizeof(wsegs)); 646. 	for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ 647. 		wheads[tmp] = wsegs[tmp] = wtmp = newseg; 648. 		while(1) { 649. 			mread(fd, (genericptr_t)wtmp, sizeof(struct wseg)); 650. 			if(!wtmp->nseg) break; 651. 			wheads[tmp]->nseg = wtmp = newseg; 652. 			wheads[tmp] = wtmp; 653. 		}  654.  	}  655.  	mread(fd, (genericptr_t)wgrowtime, sizeof(wgrowtime)); 656. #endif 657. 	/* Now get rid of all the temp fruits... */ 658.  	if (ghostly) { 659. 		struct fruit *fruit; 660.  661.  		while(oldfruit) { 662. 			fruit = oldfruit->nextf; 663. 			free((genericptr_t) oldfruit); 664. 			oldfruit = fruit; 665. 		}  666.  	}  667.  }  668.   669.  #ifdef ZEROCOMP 670. #define RLESC '\0' 	/* Leading character for run of RLESC's */ 671.  672.  static unsigned char inbuf[BUFSZ]; 673. static unsigned short inbufp = 0; 674. static unsigned short inbufsz = 0; 675. static short inrunlength = -1; 676. static int mreadfd; 677.  678.  static int 679. mgetc 680. {  681.      if (inbufp >= inbufsz) { 682.       inbufsz = read(mreadfd, (genericptr_t)inbuf, (int)sizeof inbuf); 683.       if (!inbufsz) { 684. 	  if (inbufp > sizeof inbuf) 685. 	      error("EOF on file #%d.\n", mreadfd); 686. 	  inbufp = 1 + sizeof inbuf;  /* exactly one warning :-) */  687.  	  return -1;  688.        }  689.        inbufp = 0;  690.      }  691.      return inbuf[inbufp++];  692.  }  693.   694.  void  695.  minit  696.  {  697.      inbufsz = 0;  698.      inbufp = 0;  699.      inrunlength = -1;  700.  }  701.   702.  int  703.  mread(fd, buf, len)  704.  int fd;  705.  register genericptr_t buf;  706.  register unsigned len;  707.  {  708.      /*register int readlen = 0;*/  709.      mreadfd = fd;  710.      while (len--) {  711.        if (inrunlength > 0) {  712.  	  inrunlength--;  713.  	  *((char *)buf)++ = '\0';  714.        } else {  715.  	  register short ch = mgetc;  716.  	  if (ch < 0) return -1; /*readlen;*/  717.  	  if ((*((char *)buf)++ = ch) == RLESC) {  718.  	      inrunlength = mgetc;  719.  	  }  720.        }  721.        /*readlen++;*/  722.      }  723. return 0; /*readlen;*/ 724. }  725.   726.  #else /* ZEROCOMP */ 727.  728.  void 729. mread(fd, buf, len) 730. register int fd; 731. register genericptr_t buf; 732. register unsigned int len; 733. {  734.  	register int rlen; 735.  736.  #if defined(BSD) || defined(ULTRIX) 737. 	rlen = read(fd, buf, (int) len); 738. 	if(rlen != len){ 739. #else /* e.g. SYSV, __TURBOC__ */ 740. 	rlen = read(fd, buf, (unsigned) len); 741. 	if((unsigned)rlen != len){ 742. #endif 743. 		pline("Read %d instead of %u bytes.\n", rlen, len); 744. 		if(restoring) { 745. 			(void) unlink(SAVEF); 746. 			error("Error restoring old game."); 747. 		}  748.  		panic("Error reading level file."); 749. 	}  750.  }  751.  #endif /* ZEROCOMP */