Source:NetHack 1.4f/lev.c

From NetHackWiki
Jump to: navigation, search

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