Source:NetHack 3.2.0/restore.c

From NetHackWiki
(Redirected from NetHack 3.2.0/restore.c)
Jump to navigation Jump to search

Below is the full text to restore.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/restore.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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