Source:NetHack 3.3.0/restore.c

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