Source:SLASH'EM 0.0.7E7F2/restore.c

Below is the full text to restore.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/restore.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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