Source:NetHack 1.3d/lev.c

From NetHackWiki
Jump to: navigation, search

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