Source:Restore.c

Below is the full text to src/restore.c from NetHack 3.4.3. To link to a particular line, write [[restore.c#line123 ]], for example. 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. 				impossible("bad monster weapon restore"); 297. 			}  298.  		}  299.   300.  		if (mtmp->isshk) restshk(mtmp, ghostly); 301. 		if (mtmp->ispriest) restpriest(mtmp, ghostly); 302.  303.  		mtmp2 = mtmp; 304. 	}  305.  	if(first && mtmp2->nmon){ 306. 		impossible("Restmonchn: error reading monchn."); 307. 		mtmp2->nmon = 0; 308. 	}  309.  	return(first); 310. }  311.   312.  STATIC_OVL struct fruit * 313. loadfruitchn(fd) 314. int fd; 315. {  316.  	register struct fruit *flist, *fnext; 317.  318.  	flist = 0; 319. 	while (fnext = newfruit,  320.  	       mread(fd, (genericptr_t)fnext, sizeof *fnext),  321.  	       fnext->fid != 0) { 322. 		fnext->nextf = flist; 323. 		flist = fnext; 324. 	}  325.  	dealloc_fruit(fnext); 326. 	return flist; 327. }  328.   329.  STATIC_OVL void 330. freefruitchn(flist) 331. register struct fruit *flist; 332. {  333.  	register struct fruit *fnext; 334.  335.  	while (flist) { 336. 	    fnext = flist->nextf; 337. 	    dealloc_fruit(flist); 338. 	    flist = fnext; 339. 	}  340.  }  341.   342.  STATIC_OVL void 343. ghostfruit(otmp) 344. register struct obj *otmp; 345. {  346.  	register struct fruit *oldf; 347.  348.  	for (oldf = oldfruit; oldf; oldf = oldf->nextf) 349. 		if (oldf->fid == otmp->spe) break; 350.  351.  	if (!oldf) impossible("no old fruit?"); 352. 	else otmp->spe = fruitadd(oldf->fname); 353. }  354.   355.  STATIC_OVL 356. boolean 357. restgamestate(fd, stuckid, steedid) 358. register int fd; 359. unsigned int *stuckid, *steedid;	/* STEED */ 360. {  361.  	/* discover is actually flags.explore */ 362. 	boolean remember_discover = discover; 363. 	struct obj *otmp; 364. 	int uid; 365.  366.  	mread(fd, (genericptr_t) &uid, sizeof uid); 367. 	if (uid != getuid) {		/* strange ... */ 368.  	    /* for wizard mode, issue a reminder; for others, treat it  369. as an attempt to cheat and refuse to restore this file */ 370. 	    pline("Saved game was not yours."); 371. #ifdef WIZARD 372. 	    if (!wizard) 373. #endif 374. 		return FALSE; 375. 	}  376.   377.  	mread(fd, (genericptr_t) &flags, sizeof(struct flag)); 378. 	flags.bypasses = 0;	/* never use the saved value of bypasses */ 379. 	if (remember_discover) discover = remember_discover; 380.  381.  	role_init;	/* Reset the initial role, race, gender, and alignment */ 382. #ifdef AMII_GRAPHICS 383. 	amii_setpens(amii_numcolors);	/* use colors from save file */ 384. #endif 385. 	mread(fd, (genericptr_t) &u, sizeof(struct you)); 386. 	set_uasmon; 387. #ifdef CLIPPING 388. 	cliparound(u.ux, u.uy); 389. #endif 390. 	if(u.uhp <= 0 && (!Upolyd || u.mh <= 0)) { 391. 	    u.ux = u.uy = 0;	/* affects pline [hence You] */ 392. 	    You("were not healthy enough to survive restoration."); 393. 	    /* wiz1_level.dlevel is used by mklev.c to see if lots of stuff is  394. * uninitialized, so we only have to set it and not the other stuff. 395. 	     */  396.  	    wiz1_level.dlevel = 0; 397. 	    u.uz.dnum = 0; 398. 	    u.uz.dlevel = 1; 399. 	    return(FALSE); 400. 	}  401.   402.  	/* this stuff comes after potential aborted restore attempts */ 403. 	restore_timers(fd, RANGE_GLOBAL, FALSE, 0L); 404. 	restore_light_sources(fd); 405. 	invent = restobjchn(fd, FALSE, FALSE); 406. 	migrating_objs = restobjchn(fd, FALSE, FALSE); 407. 	migrating_mons = restmonchn(fd, FALSE); 408. 	mread(fd, (genericptr_t) mvitals, sizeof(mvitals)); 409.  410.  	/* this comes after inventory has been loaded */ 411. 	for(otmp = invent; otmp; otmp = otmp->nobj) 412. 		if(otmp->owornmask) 413. 			setworn(otmp, otmp->owornmask); 414. 	/* reset weapon so that player will get a reminder about "bashing" 415. 	   during next fight when bare-handed or wielding an unconventional 416. 	   item; for pick-axe, we aren't able to distinguish between having 417. 	   applied or wielded it, so be conservative and assume the former */ 418. 	otmp = uwep;	/* `uwep' usually init'd by setworn in loop above */ 419. 	uwep = 0;	/* clear it and have setuwep reinit */ 420. 	setuwep(otmp);	/* (don't need any null check here) */ 421. 	if (!uwep || uwep->otyp == PICK_AXE || uwep->otyp == GRAPPLING_HOOK) 422. 	    unweapon = TRUE; 423.  424.  	restore_dungeon(fd); 425. 	restlevchn(fd); 426. 	mread(fd, (genericptr_t) &moves, sizeof moves); 427. 	mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves); 428. 	mread(fd, (genericptr_t) &quest_status, sizeof(struct q_score)); 429. 	mread(fd, (genericptr_t) spl_book,  430.  				sizeof(struct spell) * (MAXSPELL + 1)); 431. 	restore_artifacts(fd); 432. 	restore_oracles(fd); 433. 	if (u.ustuck) 434. 		mread(fd, (genericptr_t) stuckid, sizeof (*stuckid)); 435. #ifdef STEED 436. 	if (u.usteed) 437. 		mread(fd, (genericptr_t) steedid, sizeof (*steedid)); 438. #endif 439. 	mread(fd, (genericptr_t) pl_character, sizeof pl_character); 440.  441.  	mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit); 442. 	mread(fd, (genericptr_t) &current_fruit, sizeof current_fruit); 443. 	freefruitchn(ffruit);	/* clean up fruit(s) made by initoptions */ 444. 	ffruit = loadfruitchn(fd); 445.  446.  	restnames(fd); 447. 	restore_waterlevel(fd); 448. 	/* must come after all mons & objs are restored */ 449. 	relink_timers(FALSE); 450. 	relink_light_sources(FALSE); 451. 	return(TRUE); 452. }  453.   454.  /* update game state pointers to those valid for the current level (so we  455.   * don't dereference a wild u.ustuck when saving the game state, for instance) 456.  */  457.  STATIC_OVL void 458. restlevelstate(stuckid, steedid) 459. unsigned int stuckid, steedid;	/* STEED */ 460. {  461.  	register struct monst *mtmp; 462.  463.  	if (stuckid) { 464. 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 465. 			if (mtmp->m_id == stuckid) break; 466. 		if (!mtmp) panic("Cannot find the monster ustuck."); 467. 		u.ustuck = mtmp; 468. 	}  469.  #ifdef STEED 470. 	if (steedid) { 471. 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 472. 			if (mtmp->m_id == steedid) break; 473. 		if (!mtmp) panic("Cannot find the monster usteed."); 474. 		u.usteed = mtmp; 475. 		remove_monster(mtmp->mx, mtmp->my); 476. 	}  477.  #endif 478. }  479.   480.  /*ARGSUSED*/	/* fd used in MFLOPPY only */ 481. STATIC_OVL int 482. restlevelfile(fd, ltmp) 483. register int fd; 484. xchar ltmp; 485. #if defined(macintosh) && (defined(__SC__) || defined(__MRC__)) 486. # pragma unused(fd) 487. #endif 488. {  489.  	register int nfd; 490. 	char whynot[BUFSZ]; 491.  492.  	nfd = create_levelfile(ltmp, whynot); 493. 	if (nfd < 0) { 494. 		/* BUG: should suppress any attempt to write a panic 495. 		   save file if file creation is now failing... */ 496.  		panic("restlevelfile: %s", whynot); 497. 	}  498.  #ifdef MFLOPPY 499. 	if (!savelev(nfd, ltmp, COUNT_SAVE)) { 500.  501.  		/* The savelev can't proceed because the size required 502. 		 * is greater than the available disk space. 503. 		 */  504.  		pline("Not enough space on `%s' to restore your game.",  505.  			levels); 506.  507.  		/* Remove levels and bones that may have been created. 508. 		 */  509.  		(void) close(nfd); 510. # ifdef AMIGA 511. 		clearlocks; 512. # else 513. 		eraseall(levels, alllevels); 514. 		eraseall(levels, allbones); 515.  516.  		/* Perhaps the person would like to play without a  517. * RAMdisk. 518. 		 */  519.  		if (ramdisk) { 520. 			/* PlaywoRAMdisk may not return, but if it does 521. 			 * it is certain that ramdisk will be 0. 522. 			 */  523.  			playwoRAMdisk; 524. 			/* Rewind save file and try again */ 525. 			(void) lseek(fd, (off_t)0, 0); 526. 			(void) uptodate(fd, (char *)0);	/* skip version */ 527. 			return dorecover(fd);	/* 0 or 1 */ 528. 		} else { 529. # endif 530. 			pline("Be seeing you..."); 531. 			terminate(EXIT_SUCCESS); 532. # ifndef AMIGA 533. 		}  534.  # endif 535. 	}  536.  #endif 537. 	bufon(nfd); 538. 	savelev(nfd, ltmp, WRITE_SAVE | FREE_SAVE); 539. 	bclose(nfd); 540. 	return(2); 541. }  542.   543.  int 544. dorecover(fd) 545. register int fd; 546. {  547.  	unsigned int stuckid = 0, steedid = 0;	/* not a register */ 548. 	xchar ltmp; 549. 	int rtmp; 550. 	struct obj *otmp; 551.  552.  #ifdef STORE_PLNAME_IN_FILE 553. 	mread(fd, (genericptr_t) plname, PL_NSIZ); 554. #endif 555.  556.  	restoring = TRUE; 557. 	getlev(fd, 0, (xchar)0, FALSE); 558. 	if (!restgamestate(fd, &stuckid, &steedid)) { 559. 		display_nhwindow(WIN_MESSAGE, TRUE); 560. 		savelev(-1, 0, FREE_SAVE);	/* discard current level */ 561. 		(void) close(fd); 562. 		(void) delete_savefile; 563. 		restoring = FALSE; 564. 		return(0); 565. 	}  566.  	restlevelstate(stuckid, steedid); 567. #ifdef INSURANCE 568. 	savestateinlock; 569. #endif 570. 	rtmp = restlevelfile(fd, ledger_no(&u.uz)); 571. 	if (rtmp < 2) return(rtmp);  /* dorecover called recursively */ 572.  573.  	/* these pointers won't be valid while we're processing the 574. 	 * other levels, but they'll be reset again by restlevelstate 575. 	 * afterwards, and in the meantime at least u.usteed may mislead 576. 	 * place_monster on other levels 577. 	 */  578.  	u.ustuck = (struct monst *)0; 579. #ifdef STEED 580. 	u.usteed = (struct monst *)0; 581. #endif 582.  583.  #ifdef MICRO 584. # ifdef AMII_GRAPHICS 585. 	{  586.  	extern struct window_procs amii_procs; 587. 	if(windowprocs.win_init_nhwindows== amii_procs.win_init_nhwindows){ 588. 	    extern winid WIN_BASE; 589. 	    clear_nhwindow(WIN_BASE);	/* hack until there's a hook for this */ 590. 	}  591.  	}  592.  # else 593. 	clear_nhwindow(WIN_MAP); 594. # endif 595. 	clear_nhwindow(WIN_MESSAGE); 596. 	You("return to level %d in %s%s.",  597.  		depth(&u.uz), dungeons[u.uz.dnum].dname,  598.  		flags.debug ? " while in debug mode" :  599.  		flags.explore ? " while in explore mode" : ""); 600. 	curs(WIN_MAP, 1, 1); 601. 	dotcnt = 0; 602. 	dotrow = 2; 603. 	if (strncmpi("X11", windowprocs.name, 3)) 604.     	  putstr(WIN_MAP, 0, "Restoring:"); 605. #endif 606. 	while(1) { 607. #ifdef ZEROCOMP 608. 		if(mread(fd, (genericptr_t) &ltmp, sizeof ltmp) < 0) 609. #else 610. 		if(read(fd, (genericptr_t) &ltmp, sizeof ltmp) != sizeof ltmp) 611. #endif 612. 			break; 613. 		getlev(fd, 0, ltmp, FALSE); 614. #ifdef MICRO 615. 		curs(WIN_MAP, 1+dotcnt++, dotrow); 616. 		if (dotcnt >= (COLNO - 1)) { 617. 			dotrow++; 618. 			dotcnt = 0; 619. 		}  620.  		if (strncmpi("X11", windowprocs.name, 3)){ 621. 		  putstr(WIN_MAP, 0, "."); 622. 		}  623.  		mark_synch; 624. #endif 625. 		rtmp = restlevelfile(fd, ltmp); 626. 		if (rtmp < 2) return(rtmp);  /* dorecover called recursively */ 627. 	}  628.   629.  #ifdef BSD 630. 	(void) lseek(fd, 0L, 0); 631. #else 632. 	(void) lseek(fd, (off_t)0, 0); 633. #endif 634. 	(void) uptodate(fd, (char *)0);		/* skip version info */ 635. #ifdef STORE_PLNAME_IN_FILE 636. 	mread(fd, (genericptr_t) plname, PL_NSIZ); 637. #endif 638. 	getlev(fd, 0, (xchar)0, FALSE); 639. 	(void) close(fd); 640.  641.  	if (!wizard && !discover) 642. 		(void) delete_savefile; 643. #ifdef REINCARNATION 644. 	if (Is_rogue_level(&u.uz)) assign_rogue_graphics(TRUE); 645. #endif 646. #ifdef USE_TILES 647. 	substitute_tiles(&u.uz); 648. #endif 649. 	restlevelstate(stuckid, steedid); 650. #ifdef MFLOPPY 651. 	gameDiskPrompt; 652. #endif 653. 	max_rank_sz; /* to recompute mrank_sz (botl.c) */ 654. 	/* take care of iron ball & chain */ 655. 	for(otmp = fobj; otmp; otmp = otmp->nobj) 656. 		if(otmp->owornmask) 657. 			setworn(otmp, otmp->owornmask); 658.  659.  	/* in_use processing must be after: 660. 	 *    + The inventory has been read so that freeinv works. 661. 	 *    + The current level has been restored so billing information 662. 	 *	is available. 663. 	 */  664.  	inven_inuse(FALSE); 665.  666.  	load_qtlist;	/* re-load the quest text info */ 667. 	reset_attribute_clock; 668. 	/* Set up the vision internals, after levl[] data is loaded */ 669. 	/* but before docrt. */ 670.  	vision_reset; 671. 	vision_full_recalc = 1;	/* recompute vision (not saved) */ 672.  673.  	run_timers;	/* expire all timers that have gone off while away */ 674. 	docrt; 675. 	restoring = FALSE; 676. 	clear_nhwindow(WIN_MESSAGE); 677. 	program_state.something_worth_saving++;	/* useful data now exists */ 678.  679.  	/* Success! */ 680.  	welcome(FALSE); 681. 	return(1); 682. }  683.   684.  void 685. trickery(reason) 686. char *reason; 687. {  688.  	pline("Strange, this map is not as I remember it."); 689. 	pline("Somebody is trying some trickery here..."); 690. 	pline("This game is void."); 691. 	killer = reason; 692. 	done(TRICKED); 693. }  694.   695.  void 696. getlev(fd, pid, lev, ghostly) 697. int fd, pid; 698. xchar lev; 699. boolean ghostly; 700. {  701.  	register struct trap *trap; 702. 	register struct monst *mtmp; 703. 	branch *br; 704. 	int hpid; 705. 	xchar dlvl; 706. 	int x, y;  707. #ifdef TOS 708. 	short tlev; 709. #endif 710.  711.  	if (ghostly) 712. 	    clear_id_mapping; 713.  714.  #if defined(MSDOS) || defined(OS2) 715. 	setmode(fd, O_BINARY); 716. #endif 717. 	/* Load the old fruit info. We have to do it first, so the 718. 	 * information is available when restoring the objects. 719. 	 */  720.  	if (ghostly) oldfruit = loadfruitchn(fd); 721.  722.  	/* First some sanity checks */ 723. 	mread(fd, (genericptr_t) &hpid, sizeof(hpid)); 724. /* CHECK:  This may prevent restoration */ 725. #ifdef TOS 726. 	mread(fd, (genericptr_t) &tlev, sizeof(tlev)); 727. 	dlvl=tlev&0x00ff; 728. #else 729. 	mread(fd, (genericptr_t) &dlvl, sizeof(dlvl)); 730. #endif 731. 	if ((pid && pid != hpid) || (lev && dlvl != lev)) { 732. 	    char trickbuf[BUFSZ]; 733.  734.  	    if (pid && pid != hpid) 735. 		Sprintf(trickbuf, "PID (%d) doesn't match saved PID (%d)!",  736.  			hpid, pid); 737. 	    else 738. 		Sprintf(trickbuf, "This is level %d, not %d!", dlvl, lev); 739. #ifdef WIZARD 740. 	    if (wizard) pline(trickbuf); 741. #endif 742. 	    trickery(trickbuf); 743. 	}  744.   745.  #ifdef RLECOMP 746. 	{  747.  		short	i, j;  748. uchar	len; 749. 		struct rm r;  750. 751. #if defined(MAC) 752. 		/* Suppress warning about used before set */ 753. 		(void) memset((genericptr_t) &r, 0, sizeof(r)); 754. #endif 755. 		i = 0; j = 0; len = 0; 756. 		while(i < ROWNO) { 757. 		    while(j < COLNO) { 758. 			if(len > 0) { 759. 			    levl[j][i] = r;  760. len -= 1; 761. 			    j += 1; 762. 			} else { 763. 			    mread(fd, (genericptr_t)&len, sizeof(uchar)); 764. 			    mread(fd, (genericptr_t)&r, sizeof(struct rm)); 765. 			}  766.  		    }  767.  		    j = 0; 768. 		    i += 1; 769. 		}  770.  	}  771.  #else 772. 	mread(fd, (genericptr_t) levl, sizeof(levl)); 773. #endif	/* RLECOMP */ 774.  775.  	mread(fd, (genericptr_t)&omoves, sizeof(omoves)); 776. 	mread(fd, (genericptr_t)&upstair, sizeof(stairway)); 777. 	mread(fd, (genericptr_t)&dnstair, sizeof(stairway)); 778. 	mread(fd, (genericptr_t)&upladder, sizeof(stairway)); 779. 	mread(fd, (genericptr_t)&dnladder, sizeof(stairway)); 780. 	mread(fd, (genericptr_t)&sstairs, sizeof(stairway)); 781. 	mread(fd, (genericptr_t)&updest, sizeof(dest_area)); 782. 	mread(fd, (genericptr_t)&dndest, sizeof(dest_area)); 783. 	mread(fd, (genericptr_t)&level.flags, sizeof(level.flags)); 784. 	mread(fd, (genericptr_t)doors, sizeof(doors)); 785. 	rest_rooms(fd);		/* No joke :-) */  786.  	if (nroom)  787.  	    doorindex = rooms[nroom - 1].fdoor + rooms[nroom - 1].doorct;  788.  	else  789.  	    doorindex = 0;  790.   791.  	restore_timers(fd, RANGE_LEVEL, ghostly, monstermoves - omoves);  792.  	restore_light_sources(fd);  793.  	fmon = restmonchn(fd, ghostly);  794.   795.  	/* regenerate animals while on another level */  796.  	if (u.uz.dlevel) {  797.  	    register struct monst *mtmp2;  798.   799.  	    for (mtmp = fmon; mtmp; mtmp = mtmp2) {  800.  		mtmp2 = mtmp->nmon;  801.  		if (ghostly) {  802.  			/* reset peaceful/malign relative to new character */  803.  			if(!mtmp->isshk)  804.  				/* shopkeepers will reset based on name */  805.  				mtmp->mpeaceful = peace_minded(mtmp->data);  806.  			set_malign(mtmp);  807.  		} else if (monstermoves > omoves)  808.  			mon_catchup_elapsed_time(mtmp, monstermoves - omoves); 809.  810.  		/* update shape-changers in case protection against 811. 		   them is different now than when the level was saved */ 812. 		restore_cham(mtmp); 813. 	    }  814.  	}  815.   816.  	rest_worm(fd);	/* restore worm information */ 817. 	ftrap = 0; 818. 	while (trap = newtrap,  819.  	       mread(fd, (genericptr_t)trap, sizeof(struct trap)),  820.  	       trap->tx != 0) {	/* need "!= 0" to work around DICE 3.0 bug */ 821. 		trap->ntrap = ftrap; 822. 		ftrap = trap; 823. 	}  824.  	dealloc_trap(trap); 825. 	fobj = restobjchn(fd, ghostly, FALSE); 826. 	find_lev_obj; 827. 	/* restobjchn's `frozen' argument probably ought to be a callback 828. 	   routine so that we can check for objects being buried under ice */ 829. 	level.buriedobjlist = restobjchn(fd, ghostly, FALSE); 830. 	billobjs = restobjchn(fd, ghostly, FALSE); 831. 	rest_engravings(fd); 832.  833.  	/* reset level.monsters for new level */ 834. 	for (x = 0; x < COLNO; x++) 835. 	    for (y = 0; y < ROWNO; y++) 836. 		level.monsters[x][y] = (struct monst *) 0; 837. 	for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon) { 838. 	    if (mtmp->isshk) 839. 		set_residency(mtmp, FALSE); 840. 	    place_monster(mtmp, mtmp->mx, mtmp->my); 841. 	    if (mtmp->wormno) place_wsegs(mtmp); 842. 	}  843.  	restdamage(fd, ghostly); 844.  845.  	rest_regions(fd, ghostly); 846. 	if (ghostly) { 847. 	    /* Now get rid of all the temp fruits... */ 848.  	    freefruitchn(oldfruit),  oldfruit = 0; 849.  850.  	    if (lev > ledger_no(&medusa_level) &&  851.  			lev < ledger_no(&stronghold_level) && xdnstair == 0) { 852. 		coord cc; 853.  854.  		mazexy(&cc); 855. 		xdnstair = cc.x;  856. ydnstair = cc.y; 857. levl[cc.x][cc.y].typ = STAIRS; 858. 	    }  859.   860.  	    br = Is_branchlev(&u.uz); 861. 	    if (br && u.uz.dlevel == 1) { 862. 		d_level ltmp; 863.  864.  		if (on_level(&u.uz, &br->end1)) 865. 		    assign_level(&ltmp, &br->end2); 866. 		else 867. 		    assign_level(&ltmp, &br->end1); 868.  869.  		switch(br->type) { 870. 		case BR_STAIR: 871. 		case BR_NO_END1: 872. 		case BR_NO_END2: /* OK to assign to sstairs if it's not used */ 873. 		    assign_level(&sstairs.tolev, &ltmp); 874. 		    break; 875. 		case BR_PORTAL: /* max of 1 portal per level */ 876. 		    {  877.  			register struct trap *ttmp; 878. 			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 879. 			    if (ttmp->ttyp == MAGIC_PORTAL) 880. 				break; 881. 			if (!ttmp) panic("getlev: need portal but none found"); 882. 			assign_level(&ttmp->dst, &ltmp); 883. 		    }  884.  		    break; 885. 		}  886.  	    } else if (!br) { 887. 		/* Remove any dangling portals. */ 888.  		register struct trap *ttmp; 889. 		for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 890. 		    if (ttmp->ttyp == MAGIC_PORTAL) { 891. 			deltrap(ttmp); 892. 			break; /* max of 1 portal/level */ 893. 		    }  894.  	    }  895.  	}  896.   897.  	/* must come after all mons & objs are restored */ 898. 	relink_timers(ghostly); 899. 	relink_light_sources(ghostly); 900. 	reset_oattached_mids(ghostly); 901.  902.  	if (ghostly) 903. 	    clear_id_mapping; 904. }  905.   906.   907.  /* Clear all structures for object and monster ID mapping. */ 908.  STATIC_OVL void 909. clear_id_mapping 910. {  911.      struct bucket *curr; 912.  913.      while ((curr = id_map) != 0) { 914. 	id_map = curr->next; 915. 	free((genericptr_t) curr); 916.     }  917.      n_ids_mapped = 0; 918. }  919.   920.  /* Add a mapping to the ID map. */ 921.  STATIC_OVL void 922. add_id_mapping(gid, nid) 923.     unsigned gid, nid; 924. {  925.      int idx; 926.  927.      idx = n_ids_mapped % N_PER_BUCKET; 928.     /* idx is zero on first time through, as well as when a new bucket is */ 929.     /* needed */ 930.     if (idx == 0) { 931. 	struct bucket *gnu = (struct bucket *) alloc(sizeof(struct bucket)); 932. 	gnu->next = id_map; 933. 	id_map = gnu; 934.     }  935.   936.      id_map->map[idx].gid = gid; 937.     id_map->map[idx].nid = nid; 938.     n_ids_mapped++; 939. }  940.   941.  /*  942.   * Global routine to look up a mapping. If found, return TRUE and fill 943.  * in the new ID value. Otherwise, return false and return -1 in the new 944.  * ID. 945.  */  946.  boolean 947. lookup_id_mapping(gid, nidp) 948.     unsigned gid, *nidp; 949. {  950.      int i;  951. struct bucket *curr; 952.  953.      if (n_ids_mapped) 954. 	for (curr = id_map; curr; curr = curr->next) { 955. 	    /* first bucket might not be totally full */ 956. 	    if (curr == id_map) { 957. 		i = n_ids_mapped % N_PER_BUCKET; 958. 		if (i == 0) i = N_PER_BUCKET; 959. 	    } else 960. 		i = N_PER_BUCKET; 961.  962.  	    while (--i >= 0) 963. 		if (gid == curr->map[i].gid) { 964. 		    *nidp = curr->map[i].nid; 965. 		    return TRUE; 966. 		}  967.  	}  968.   969.      return FALSE; 970. }  971.   972.  STATIC_OVL void 973. reset_oattached_mids(ghostly) 974. boolean ghostly; 975. {  976.      struct obj *otmp; 977.     unsigned oldid, nid; 978.     for (otmp = fobj; otmp; otmp = otmp->nobj) { 979. 	if (ghostly && otmp->oattached == OATTACHED_MONST && otmp->oxlth) { 980. 	    struct monst *mtmp = (struct monst *)otmp->oextra; 981.  982.  	    mtmp->m_id = 0; 983. 	    mtmp->mpeaceful = mtmp->mtame = 0;	/* pet's owner died! */ 984.  	}  985.  	if (ghostly && otmp->oattached == OATTACHED_M_ID) { 986. 	    (void) memcpy((genericptr_t)&oldid, (genericptr_t)otmp->oextra,  987.  								sizeof(oldid)); 988. 	    if (lookup_id_mapping(oldid, &nid)) 989. 		(void) memcpy((genericptr_t)otmp->oextra, (genericptr_t)&nid,  990.  								sizeof(nid)); 991. 	    else 992. 		otmp->oattached = OATTACHED_NOTHING; 993. 	}  994.      }  995.  }  996.   997.   998.  #ifdef ZEROCOMP 999. #define RLESC '\0'	/* Leading character for run of RLESC's */ 1000. 1001. #ifndef ZEROCOMP_BUFSIZ 1002. #define ZEROCOMP_BUFSIZ BUFSZ 1003. #endif 1004. static NEARDATA unsigned char inbuf[ZEROCOMP_BUFSIZ]; 1005. static NEARDATA unsigned short inbufp = 0; 1006. static NEARDATA unsigned short inbufsz = 0; 1007. static NEARDATA short inrunlength = -1; 1008. static NEARDATA int mreadfd; 1009. 1010. static int 1011. mgetc 1012. { 1013.     if (inbufp >= inbufsz) { 1014. 	inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf); 1015. 	if (!inbufsz) { 1016. 	   if (inbufp > sizeof inbuf) 1017. 		error("EOF on file #%d.\n", mreadfd); 1018. 	   inbufp = 1 + sizeof inbuf;  /* exactly one warning :-) */  1019. 	    return -1;  1020. 	}  1021. 	inbufp = 0;  1022.     }  1023.     return inbuf[inbufp++];  1024. }  1025.  1026. void  1027. minit  1028. {  1029.     inbufsz = 0;  1030.     inbufp = 0;  1031.     inrunlength = -1;  1032. }  1033.  1034. int  1035. mread(fd, buf, len)  1036. int fd;  1037. genericptr_t buf;  1038. register unsigned len;  1039. {  1040.     /*register int readlen = 0;*/  1041.     if (fd < 0) error("Restore error; mread attempting to read file %d.", fd);  1042.     mreadfd = fd;  1043.     while (len--) {  1044. 	if (inrunlength > 0) {  1045. 	    inrunlength--;  1046. 	    *(*((char **)&buf))++ = '\0';  1047. 	} else {  1048. 	    register short ch = mgetc;  1049. 	    if (ch < 0) return -1; /*readlen;*/  1050. 	    if ((*(*(char **)&buf)++ = (char)ch) == RLESC) {  1051. 		inrunlength = mgetc; 1052. 	   }  1053. 	}  1054. 	/*readlen++;*/ 1055.    }  1056.     return 0; /*readlen;*/ 1057. } 1058.  1059. #else /* ZEROCOMP */ 1060. 1061. void 1062. minit 1063. { 1064.     return; 1065. } 1066.  1067. void 1068. mread(fd, buf, len) 1069. register int fd; 1070. register genericptr_t buf; 1071. register unsigned int len; 1072. { 1073. 	register int rlen; 1074. 1075. #if defined(BSD) || defined(ULTRIX) 1076. 	rlen = read(fd, buf, (int) len); 1077. 	if(rlen != len){ 1078. #else /* e.g. SYSV, __TURBOC__ */ 1079. 	rlen = read(fd, buf, (unsigned) len); 1080. 	if((unsigned)rlen != len){ 1081. #endif 1082. 		pline("Read %d instead of %u bytes.", rlen, len); 1083. 		if(restoring) { 1084. 			(void) close(fd); 1085. 			(void) delete_savefile; 1086. 			error("Error restoring old game."); 1087. 		} 1088. 		panic("Error reading level file."); 1089. 	} 1090. }  1091. #endif /* ZEROCOMP */ 1092. 1093. /*restore.c*/