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