Source:NetHack 3.4.0/restore.c

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