Source:NetHack 2.2a/lev.c

From NetHackWiki
Jump to navigation Jump to search

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

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

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)lev.c	2.1	87/10/19
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    
4.    #include <stdio.h>
5.    #include "hack.h"
6.    #include "mkroom.h"
7.    extern struct monst *restmonchn();
8.    extern struct obj *restobjchn();
9.    extern struct obj *billobjs;
10.   extern char *itoa();
11.   extern char SAVEF[];
12.   extern int hackpid;
13.   extern xchar dlevel;
14.   extern char nul[];
15.   
16.   #ifndef NOWORM
17.   #include	"wseg.h"
18.   extern struct wseg *wsegs[32], *wheads[32];
19.   extern long wgrowtime[32];
20.   #endif
21.   
22.   #ifdef DGK
23.   struct finfo fileinfo[MAXLEVEL+1];
24.   long bytes_counted;
25.   int count_only;
26.   #else
27.   boolean level_exists[MAXLEVEL+1];
28.   #endif
29.   
30.   #ifdef DGK
31.   savelev(fd, lev, mode)
32.   int fd, mode;
33.   xchar lev;
34.   {
35.   	if (mode & COUNT) {
36.   		count_only = TRUE;
37.   		bytes_counted = 0;
38.   		savelev0(fd, lev);
39.   		while (bytes_counted > freediskspace(levels))
40.   			if (!swapout_oldest())
41.   				return FALSE;
42.   	}
43.   	if (mode & WRITE) {
44.   		count_only = FALSE;
45.   		bytes_counted = 0;
46.   		savelev0(fd, lev);
47.   	}
48.   	fileinfo[lev].where = ACTIVE;
49.   	fileinfo[lev].time = moves;
50.   	fileinfo[lev].size = bytes_counted;
51.   	return TRUE;
52.   }
53.   
54.   savelev0(fd,lev)
55.   #else
56.   savelev(fd,lev)
57.   #endif
58.   int fd;
59.   xchar lev;
60.   {
61.   #ifndef NOWORM
62.   	register struct wseg *wtmp, *wtmp2;
63.   	register tmp;
64.   #endif
65.   
66.   	if(fd < 0) panic("Save on bad file!");	/* impossible */
67.   #ifndef DGK
68.   	if(lev >= 0 && lev <= MAXLEVEL)
69.   		level_exists[lev] = TRUE;
70.   #endif
71.   	bwrite(fd,(char *) &hackpid,sizeof(hackpid));
72.   	bwrite(fd,(char *) &lev,sizeof(lev));
73.   	bwrite(fd,(char *) levl,sizeof(levl));
74.   #ifdef GRAPHICS
75.   	bwrite(fd, (char *) &showsyms, sizeof(struct symbols));
76.   #endif
77.   	bwrite(fd,(char *) &moves,sizeof(long));
78.   	bwrite(fd,(char *) &xupstair,sizeof(xupstair));
79.   	bwrite(fd,(char *) &yupstair,sizeof(yupstair));
80.   	bwrite(fd,(char *) &xdnstair,sizeof(xdnstair));
81.   	bwrite(fd,(char *) &ydnstair,sizeof(ydnstair));
82.   	savemonchn(fd, fmon);
83.   	savegoldchn(fd, fgold);
84.   	savetrapchn(fd, ftrap);
85.   	saveobjchn(fd, fobj);
86.   	saveobjchn(fd, billobjs);
87.   	billobjs = 0;
88.   	save_engravings(fd);
89.   #ifndef QUEST
90.   	bwrite(fd,(char *) rooms,sizeof(rooms));
91.   	bwrite(fd,(char *) doors,sizeof(doors));
92.   #endif
93.   #ifdef DGK
94.   	if (!count_only)
95.   #endif
96.   	{
97.   		fgold = 0;
98.   		ftrap = 0;
99.   		fmon = 0;
100.  		fobj = 0;
101.  	}
102.  #ifndef NOWORM
103.  	bwrite(fd,(char *) wsegs,sizeof(wsegs));
104.  	for(tmp=1; tmp<32; tmp++){
105.  		for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){
106.  			wtmp2 = wtmp->nseg;
107.  			bwrite(fd,(char *) wtmp,sizeof(struct wseg));
108.  		}
109.  #ifdef DGK
110.  		if (!count_only)
111.  #endif
112.  			wsegs[tmp] = 0;
113.  	}
114.  	bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime));
115.  #endif /* NOWORM /**/
116.  #ifdef DGK
117.  	if (count_only)	return(0);
118.  #endif
119.  	billobjs = 0;
120.  	fgold = 0;
121.  	ftrap = 0;
122.  	fmon = 0;
123.  	fobj = 0;
124.  }
125.  
126.  bwrite(fd,loc,num)
127.  register fd;
128.  register char *loc;
129.  register unsigned num;
130.  {
131.  #ifdef DGK
132.  	bytes_counted += num;
133.  	if (!count_only)
134.  #endif
135.  /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */
136.  	    if(write(fd, loc, (int) num) != num)
137.  		panic("cannot write %u bytes to file #%d", num, fd);
138.  }
139.  
140.  saveobjchn(fd,otmp)
141.  register fd;
142.  register struct obj *otmp;
143.  {
144.  	register struct obj *otmp2;
145.  	unsigned xl;
146.  	int minusone = -1;
147.  
148.  	while(otmp) {
149.  		otmp2 = otmp->nobj;
150.  		xl = otmp->onamelth;
151.  		bwrite(fd, (char *) &xl, sizeof(int));
152.  		bwrite(fd, (char *) otmp, xl + sizeof(struct obj));
153.  #ifdef DGK
154.  		if (!count_only)
155.  #endif
156.  			free((char *) otmp);
157.  		otmp = otmp2;
158.  	}
159.  	bwrite(fd, (char *) &minusone, sizeof(int));
160.  }
161.  
162.  #ifdef MSDOS
163.  /* We don't want to save any pointers in any files, so convert
164.   * the pointers to indices before writing the monsters to disk -dgk
165.   */
166.  savemonchn(fd,mtmp)
167.  register fd;
168.  register struct monst *mtmp;
169.  {
170.  	register struct monst *mtmp2;
171.  	unsigned xl;
172.  	int minusone = -1;
173.  	struct permonst *permonstp;
174.  	int monsindex;
175.  	extern struct permonst li_dog, dog, la_dog;
176.  #ifdef KAA
177.  	int mi;
178.  	extern struct permonst hell_hound;
179.  # ifdef HARD
180.  	extern struct permonst d_lord, d_prince;
181.  # endif
182.  # ifdef KJSMODS
183.  	extern struct permonst pm_guard, pm_ghost, pm_eel;
184.  # endif
185.  #endif /* KAA /**/
186.  
187.  	while(mtmp) {
188.  		mtmp2 = mtmp->nmon;
189.  		xl = mtmp->mxlth + mtmp->mnamelth;
190.  		bwrite(fd, (char *) &xl, sizeof(int));
191.  		/* store an index where the pointer used to be */
192.  		permonstp = mtmp->data;
193.  		if (permonstp == &li_dog)
194.  			monsindex = mi = -1;	/* fake index */
195.  		else if (permonstp == &dog)
196.  			monsindex = --mi;	/* fake index */
197.  		else if (permonstp == &la_dog)
198.  			monsindex = --mi;	/* fake index */
199.  #ifdef KAA
200.  		else if (permonstp == &hell_hound)
201.  			monsindex = --mi;	/* fake index */
202.  # ifdef HARD
203.  		else if (permonstp == &d_lord)
204.  			monsindex = --mi;	/* fake index */
205.  
206.  		else if (permonstp == &d_prince)
207.  			monsindex = --mi;	/* fake index */
208.  # endif
209.  # ifdef KJSMODS
210.  		else if (permonstp == &pm_guard)
211.  			monsindex = -mi;	/* fake index */
212.  
213.  		else if (permonstp == &pm_ghost)
214.  			monsindex = -mi;	/* fake index */
215.  
216.  		else if (permonstp == &pm_eel)
217.  			monsindex = -mi;	/* fake index */
218.  # endif
219.  #endif
220.  		else			
221.  			monsindex = permonstp - &mons[0];
222.  		*((int *)&mtmp->data) = monsindex;
223.  		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
224.  		mtmp->data = permonstp;		/* restore the pointer */
225.  		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
226.  #ifdef DGK
227.  		if (!count_only)
228.  #endif
229.  			free((char *) mtmp);
230.  		mtmp = mtmp2;
231.  	}
232.  	bwrite(fd, (char *) &minusone, sizeof(int));
233.  }
234.  #else
235.  
236.  savemonchn(fd,mtmp)
237.  register fd;
238.  register struct monst *mtmp;
239.  {
240.  	register struct monst *mtmp2;
241.  	unsigned xl;
242.  	int minusone = -1;
243.  	struct permonst *monbegin = &mons[0];
244.  
245.  	bwrite(fd, (char *) &monbegin, sizeof(monbegin));
246.  
247.  	while(mtmp) {
248.  		mtmp2 = mtmp->nmon;
249.  		xl = mtmp->mxlth + mtmp->mnamelth;
250.  		bwrite(fd, (char *) &xl, sizeof(int));
251.  		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
252.  		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
253.  		free((char *) mtmp);
254.  		mtmp = mtmp2;
255.  	}
256.  	bwrite(fd, (char *) &minusone, sizeof(int));
257.  }
258.  #endif
259.  
260.  savegoldchn(fd,gold)
261.  register fd;
262.  register struct gold *gold;
263.  {
264.  	register struct gold *gold2;
265.  	while(gold) {
266.  		gold2 = gold->ngold;
267.  		bwrite(fd, (char *) gold, sizeof(struct gold));
268.  #ifdef DGK
269.  		if (!count_only)
270.  #endif
271.  			free((char *) gold);
272.  		gold = gold2;
273.  	}
274.  	bwrite(fd, nul, sizeof(struct gold));
275.  }
276.  
277.  savetrapchn(fd,trap)
278.  register fd;
279.  register struct trap *trap;
280.  {
281.  	register struct trap *trap2;
282.  	while(trap) {
283.  		trap2 = trap->ntrap;
284.  		bwrite(fd, (char *) trap, sizeof(struct trap));
285.  #ifdef DGK
286.  		if (!count_only)
287.  #endif
288.  			free((char *) trap);
289.  		trap = trap2;
290.  	}
291.  	bwrite(fd, nul, sizeof(struct trap));
292.  }
293.  
294.  getlev(fd,pid,lev)
295.  int fd,pid;
296.  xchar lev;
297.  {
298.  	register struct gold *gold;
299.  	register struct trap *trap;
300.  #ifndef NOWORM
301.  	register struct wseg *wtmp;
302.  #endif
303.  	register tmp;
304.  	long omoves;
305.  	int hpid;
306.  	xchar dlvl;
307.  #ifdef GRAPHICS
308.  	struct symbols osymbol;
309.  	int x, y, up, dn, lt, rt;
310.  	uchar osym, nsym;
311.  #endif
312.  
313.  #ifdef MSDOS
314.  	setmode(fd,O_BINARY);
315.  #endif
316.  	/* First some sanity checks */
317.  	mread(fd, (char *) &hpid, sizeof(hpid));
318.  	mread(fd, (char *) &dlvl, sizeof(dlvl));
319.  	if((pid && pid != hpid) || (lev && dlvl != lev)) {
320.  		pline("Strange, this map is not as I remember it.");
321.  		pline("Somebody is trying some trickery here ...");
322.  		pline("This game is void ...");
323.  		done("tricked");
324.  	}
325.  
326.  	fgold = 0;
327.  	ftrap = 0;
328.  	mread(fd, (char *) levl, sizeof(levl));
329.  #ifdef GRAPHICS
330.  	/* Corners are poorly implemented.  They only exist in the
331.  	 * scrsym field of each dungeon element.  So we have to go
332.  	 * through the previous level, looking for scrsym with the
333.  	 * old corner values, checking to make sure that they are
334.  	 * where corners should be, then replace them with the scrsym
335.  	 * of the new GRAPHICS character set.  Ugly.
336.  	 */
337.  	mread(fd, (char *) &osymbol, sizeof(osymbol));
338.  	if (memcmp((char *) &osymbol, (char *) &showsyms, sizeof (struct symbols))) {
339.  		for (x = 0; x < COLNO; x++)
340.  			for (y = 0; y < ROWNO; y++) {
341.  				osym = levl[x][y].scrsym;
342.  				nsym = 0;
343.  				switch (levl[x][y].typ) {
344.  				case 0:
345.  				case SCORR:
346.  					break;
347.  				case ROOM:
348.  					if (osym == osymbol.room)
349.  						nsym = showsyms.room;
350.  					break;
351.  				case DOOR:
352.  					if (osym == osymbol.door)
353.  						nsym = showsyms.door;
354.  					break;
355.  				case CORR:
356.  					if (osym == osymbol.corr)
357.  						nsym = showsyms.corr;
358.  					break;
359.  				case VWALL:
360.  					if (osym == osymbol.vwall)
361.  						nsym = showsyms.vwall;
362.  					break;
363.  				case SDOOR:
364.  					if (osym == osymbol.vwall)
365.  						nsym = showsyms.vwall;
366.  					else if (osym == osymbol.hwall)
367.  						nsym = showsyms.hwall;
368.  					break;
369.  				/* Now the ugly stuff */
370.  				case HWALL:
371.  				  up = (y > 0) ? levl[x][y-1].typ : 0;
372.  				  dn = (y < ROWNO-1) ?levl[x][y+1].typ : 0;
373.  				  lt = (x > 0) ? levl[x-1][y].typ : 0;
374.  				  rt = (x < COLNO-1) ?levl[x+1][y].typ : 0;
375.  				  up = up && (up == VWALL || up == DOOR
376.  					|| up == SDOOR);
377.  				  dn = dn && (dn == VWALL || dn == DOOR
378.  					|| dn == SDOOR);
379.  				  lt = lt && (lt == HWALL || lt == DOOR
380.  					|| lt == SDOOR);
381.  				  rt = rt && (rt == HWALL || rt == DOOR
382.  					|| rt == SDOOR);
383.  				  if (rt && dn && osym == osymbol.tlcorn)
384.  					nsym = showsyms.tlcorn;
385.  				  else if (lt && dn && osym == osymbol.trcorn)
386.  					nsym = showsyms.trcorn;
387.  				  else if (rt && up && osym == osymbol.blcorn)
388.  					nsym = showsyms.blcorn;
389.  				  else if (lt && up && osym == osymbol.brcorn)
390.  					nsym = showsyms.brcorn;
391.  				  else if (osym == osymbol.hwall)
392.  					nsym = showsyms.hwall;
393.  				  break;
394.  				default:
395.  					break;
396.  				}
397.  				if (nsym)
398.  					levl[x][y].scrsym = nsym;
399.  			}
400.  	}
401.  #endif
402.  	mread(fd, (char *)&omoves, sizeof(omoves));
403.  	mread(fd, (char *)&xupstair, sizeof(xupstair));
404.  	mread(fd, (char *)&yupstair, sizeof(yupstair));
405.  	mread(fd, (char *)&xdnstair, sizeof(xdnstair));
406.  	mread(fd, (char *)&ydnstair, sizeof(ydnstair));
407.  
408.  	fmon = restmonchn(fd);
409.  
410.  	/* regenerate animals while on another level */
411.  	{ long tmoves = (moves > omoves) ? moves-omoves : 0;
412.  	  register struct monst *mtmp, *mtmp2;
413.  	  extern char genocided[];
414.  
415.  	  for(mtmp = fmon; mtmp; mtmp = mtmp2) {
416.  		long newhp;		/* tmoves may be very large */
417.  
418.  		mtmp2 = mtmp->nmon;
419.  		if(index(genocided, mtmp->data->mlet)) {
420.  			mondead(mtmp);
421.  			continue;
422.  		}
423.  
424.  		if(mtmp->mtame && tmoves > 250) {
425.  			mtmp->mtame = 0;
426.  			mtmp->mpeaceful = 0;
427.  		}
428.  
429.  		/* restore shape changers - Maarten Jan Huisjes */
430.  		if (mtmp->data->mlet == ':' && !Protection_from_shape_changers
431.  		    && !mtmp->cham) 
432.  			mtmp->cham = 1;
433.  		else if(mtmp->cham && Protection_from_shape_changers) {
434.  			mtmp->cham = 0;
435.  			(void) newcham(mtmp, PM_CHAMELEON);
436.  		}
437.  
438.  		newhp = mtmp->mhp +
439.  			(index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20);
440.  		if(newhp > mtmp->mhpmax)
441.  			mtmp->mhp = mtmp->mhpmax;
442.  		else
443.  			mtmp->mhp = newhp;
444.  	  }
445.  	}
446.  
447.  	setgd();
448.  	gold = newgold();
449.  	mread(fd, (char *)gold, sizeof(struct gold));
450.  	while(gold->gx) {
451.  		gold->ngold = fgold;
452.  		fgold = gold;
453.  		gold = newgold();
454.  		mread(fd, (char *)gold, sizeof(struct gold));
455.  	}
456.  	free((char *) gold);
457.  	trap = newtrap();
458.  	mread(fd, (char *)trap, sizeof(struct trap));
459.  	while(trap->tx) {
460.  		trap->ntrap = ftrap;
461.  		ftrap = trap;
462.  		trap = newtrap();
463.  		mread(fd, (char *)trap, sizeof(struct trap));
464.  	}
465.  	free((char *) trap);
466.  	fobj = restobjchn(fd);
467.  	billobjs = restobjchn(fd);
468.  	rest_engravings(fd);
469.  #ifndef QUEST
470.  	mread(fd, (char *)rooms, sizeof(rooms));
471.  	mread(fd, (char *)doors, sizeof(doors));
472.  #endif
473.  #ifndef NOWORM
474.  	mread(fd, (char *)wsegs, sizeof(wsegs));
475.  	for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){
476.  		wheads[tmp] = wsegs[tmp] = wtmp = newseg();
477.  		while(1) {
478.  			mread(fd, (char *)wtmp, sizeof(struct wseg));
479.  			if(!wtmp->nseg) break;
480.  			wheads[tmp]->nseg = wtmp = newseg();
481.  			wheads[tmp] = wtmp;
482.  		}
483.  	}
484.  	mread(fd, (char *)wgrowtime, sizeof(wgrowtime));
485.  #endif
486.  }
487.  
488.  mread(fd, buf, len)
489.  register fd;
490.  register char *buf;
491.  register unsigned len;
492.  {
493.  	register int rlen;
494.  	extern boolean restoring;
495.  
496.  	rlen = read(fd, buf, (int) len);
497.  	if(rlen != len){
498.  		pline("Read %d instead of %u bytes.\n", rlen, len);
499.  		if(restoring) {
500.  			(void) unlink(SAVEF);
501.  			error("Error restoring old game.");
502.  		}
503.  		panic("Error reading level file.");
504.  	}
505.  }
506.  
507.  mklev()
508.  {
509.  	extern boolean in_mklev;
510.  
511.  	if(getbones()) return;
512.  
513.  	in_mklev = TRUE;
514.  	makelevel();
515.  	in_mklev = FALSE;
516.  }
517.  
518.  #ifdef DGK
519.  swapin_file(lev) {
520.  	char to[PATHLEN], from[PATHLEN];
521.  
522.  	sprintf(from, "%s%s", permbones, alllevels);
523.  	sprintf(to, "%s%s", levels, alllevels);
524.  	name_file(from, lev);
525.  	name_file(to, lev);
526.  	while (fileinfo[lev].size > freediskspace(to)) 
527.  		if (!swapout_oldest())
528.  			return FALSE;
529.  #ifdef WIZARD
530.  	if (wizard) {
531.  		pline("Swapping in `%s'", from);
532.  		fflush(stdout);
533.  	}
534.  #endif
535.  	copyfile(from, to);
536.  	(void) unlink(from);
537.  	fileinfo[lev].where = ACTIVE;
538.  	return TRUE;
539.  }
540.  
541.  
542.  swapout_oldest() {
543.  	char to[PATHLEN], from[PATHLEN];
544.  	int i, oldest;
545.  	long oldtime;
546.  
547.  	if (!ramdisk)
548.  		return FALSE;
549.  	for (i = 1, oldtime = 0, oldest = 0; i <= maxdlevel; i++)
550.  		if (fileinfo[i].where == ACTIVE
551.  		&& (!oldtime || fileinfo[i].time < oldtime)) {
552.  			oldest = i;
553.  			oldtime = fileinfo[i].time;
554.  		}
555.  	if (!oldest)
556.  		return FALSE;
557.  	sprintf(from, "%s%s", levels, alllevels);
558.  	sprintf(to, "%s%s", permbones, alllevels);
559.  	name_file(from, oldest);
560.  	name_file(to, oldest);
561.  #ifdef WIZARD
562.  	if (wizard) {
563.  		pline("Swapping out `%s'.", from);
564.  		fflush(stdout);
565.  	}
566.  #endif
567.  	copyfile(from, to);
568.  	unlink(from);
569.  	fileinfo[oldest].where = SWAPPED;
570.  	return TRUE;
571.  }
572.  
573.  copyfile(from, to)
574.  char *from, *to;
575.  {
576.  	char buf[BUFSIZ];
577.  	int nfrom, nto, fdfrom, fdto;
578.  
579.  	if ((fdfrom = open(from, O_RDONLY | O_BINARY | O_CREAT, FMASK)) < 0)
580.  		panic("Can't copy from %s !?", from);
581.  	if ((fdto = open(to, O_WRONLY | O_BINARY | O_CREAT, FMASK)) < 0)
582.  		panic("Can't copy to %s", to);
583.  	do {
584.  		nfrom = read(fdfrom, buf, BUFSIZ);
585.  		nto = write(fdto, buf, nfrom);
586.  		if (nto != nfrom)
587.  			panic("Copyfile failed!");
588.  	} while (nfrom == BUFSIZ);
589.  	close(fdfrom);
590.  	close(fdto);
591.  }
592.  #endif