Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/restore.c

2,035pages on
this wiki
Add New Page
Talk0

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

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


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

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.