Source:NetHack 3.1.0/restore.c

From NetHackWiki
Jump to navigation Jump to search

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