Source:Hack 1.0/mklev.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to mklev.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/mklev.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.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2.    
3.    #include <stdio.h>
4.    #include "mklev.h"
5.    #include "def.trap.h"
6.    
7.    extern char *getlogin();
8.    extern struct monst *makemon();
9.    
10.   char *tfile,*tspe,**args;
11.   char nul[40];
12.   
13.   #include "savelev.h"
14.   
15.   #ifdef WIZARD
16.   boolean wizard;
17.   #endif WIZARD
18.   
19.   
20.   #define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx)
21.   #define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly)
22.   
23.   struct rm levl[COLNO][ROWNO];
24.   struct monst *fmon;
25.   struct obj *fobj;
26.   struct gen *fgold, *ftrap;
27.   
28.   char *fut_geno;		/* monsters that should not be created anymore */
29.   
30.   struct mkroom rooms[MAXNROFROOMS+1], *croom, *troom;
31.   coord doors[DOORMAX];
32.   int doorindex = 0;
33.   int comp();
34.   
35.   xchar dlevel;
36.   schar nxcor,xx,yy,dx,dy,tx,ty; /* for corridors and other things... */
37.   boolean goldseen;
38.   int nroom;
39.   
40.   xchar xdnstair,xupstair,ydnstair,yupstair;
41.   
42.   
43.   main(argc,argv)
44.   char *argv[];
45.   {
46.   	register unsigned tryct;
47.   
48.   	if(argc < 6) panic("Too few arguments!!");
49.   	args = argv;
50.   	tfile = argv[1];
51.   	tspe = argv[2];
52.   	dlevel = atoi(argv[3]);
53.   	if(dlevel < 1) panic("Bad level");
54.   	fut_geno = argv[4];
55.   #ifdef WIZARD
56.   	wizard = (argv[5][0] == 'w');
57.   #endif WIZARD
58.   	(void) srand(getpid());
59.   	init_objects();
60.   	rooms[0].hx = -1;	/* in case we are in a maze */
61.   
62.   	/* a: normal; b: maze */
63.   	if(*tspe == 'b') {
64.   		makemaz();
65.   		savelev();
66.   		exit(0);
67.   	}
68.   
69.   	/* construct the rooms */
70.   	while(nroom < (MAXNROFROOMS/3)) {
71.   		croom = rooms;
72.   		nroom = 0;
73.   		(void) makerooms(0);		/* not secret */
74.   	}
75.   
76.   	/* for each room: put things inside */
77.   	for(croom = rooms; croom->hx > 0; croom++) {
78.   
79.   		/* put a sleeping monster inside */
80.   		if(!rn2(3)) (void)
81.   			makemon((struct permonst *) 0, somex(), somey());
82.   
83.   		/* put traps and mimics inside */
84.   		goldseen = FALSE;
85.   		while(!rn2(8-(dlevel/6))) mktrap(0,0);
86.   		if(!goldseen && !rn2(3)) mkgold(0,somex(),somey());
87.   		if(!rn2(3)) {
88.   			mkobj_at(0, somex(), somey());
89.   			tryct = 0;
90.   			while(!rn2(5)) {
91.   				if(++tryct > 100){
92.   					printf("tryct overflow4\n");
93.   					break;
94.   				}
95.    mkobj_at(0, somex(), somey());
96.   			}
97.   		}
98.   	}
99.   	tryct = 0;
100.  	do {
101.  		if(++tryct > 1000) panic("Cannot make dnstairs\n");
102.  		croom = &rooms[rn2(nroom)];
103.  		xdnstair = somex();
104.  		ydnstair = somey();
105.  	} while((*tspe =='n' && (!(xdnstair%2) || !(ydnstair%2))) ||
106.  		g_at(xdnstair,ydnstair,ftrap));
107.  	levl[xdnstair][ydnstair].scrsym ='>';
108.  	levl[xdnstair][ydnstair].typ = STAIRS;
109.  	troom = croom;
110.  	do {
111.  		if(++tryct > 2000) panic("Cannot make upstairs\n");
112.  		croom = &rooms[rn2(nroom)];
113.  		xupstair = somex();
114.  		yupstair = somey();
115.  	} while(croom == troom || m_at(xupstair,yupstair) ||
116.  		g_at(xupstair,yupstair,ftrap));
117.  	levl[xupstair][yupstair].scrsym ='<';
118.  	levl[xupstair][yupstair].typ = STAIRS;
119.  
120.  	qsort((char *) rooms, nroom, sizeof(struct mkroom), comp);
121.  	croom = rooms;
122.  	troom = croom+1;
123.  	nxcor = 0;
124.  	mkpos();
125.  	do makecor();
126.  	while (croom->hx > 0 && troom->hx > 0);
127.  
128.  	/* make a secret treasure vault, not connected to the rest */
129.  	if(nroom < (2*MAXNROFROOMS/3)) if(!rn2(3)) {
130.  		register int x,y;
131.  		troom = croom = &rooms[nroom];
132.  		if(makerooms(1)) {		/* make secret room */
133.  			troom->rtype = 6;		/* treasure vault */
134.  			for(x = troom->lx; x <= troom->hx; x++)
135.  			for(y = troom->ly; y <= troom->hy; y++)
136.  				mkgold(rnd(dlevel*100) + 50, x, y);
137.  		}
138.  	}
139.  
140.  #ifdef WIZARD
141.  	if(wizard){
142.  		if(rn2(3)) mkshop(); else mkzoo();
143.  	} else
144.  #endif WIZARD
145.   	if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 2) mkshop();
146.  	else
147.  	if(dlevel > 6 && (!rn2(7) || !strcmp("david", getlogin())))
148.  		mkzoo();
149.  	savelev();
150.  	exit(0);
151.  }
152.  
153.  makerooms(secret) int secret; {
154.  register int lowx, lowy;
155.  register int tryct = 0;
156.  	while(nroom < (MAXNROFROOMS/2) || secret)
157.  	    for(lowy = rn1(3,3); lowy < ROWNO-7; lowy += rn1(2,4)) {
158.  		for(lowx = rn1(3,4); lowx < COLNO-10; lowx += rn1(2,7)) {
159.  			if(tryct++ > 10000) return(0);
160.  			if((lowy += (rn2(5)-2)) < 3) lowy = 3;
161.  			else if(lowy > ROWNO-6) lowy = ROWNO-6;
162.  			if(levl[lowx][lowy].typ) continue;
163.  			if((secret && maker(lowx, 1, lowy, 1)) ||
164.  			   (!secret && maker(lowx,rn1(9,2),lowy,rn1(4,2))
165.  				&& nroom+2 > MAXNROFROOMS)) return(1);
166.  		}
167.  	}
168.   return(1);
169.  }
170.  
171.  comp(x,y)
172.  register struct mkroom *x,*y;
173.  {
174.  	if(x->lx < y->lx) return(-1);
175.  	return(x->lx > y->lx);
176.  }
177.  
178.  coord
179.  finddpos(xl,yl,xh,yh) {
180.  coord ff;
181.  register x,y;
182.  	ff.x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
183.  	ff.y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
184.  	if(okdoor(ff.x, ff.y)) return(ff);
185.  	if(xl < xh) for(x = xl; x <= xh; x++)
186.  		if(okdoor(x, ff.y)){
187.  			ff.x = x;
188.  			return(ff);
189.  		}
190.  	if(yl < yh) for(y = yl; y <= yh; y++)
191.  		if(okdoor(ff.x, y)){
192.  			ff.y = y;
193.  			return(ff);
194.  		}
195.   return(ff);
196.  }
197.  
198.  /* when croom and troom exist, find position for a door in croom
199.     and direction for a corridor towards position [tx,ty] in the wall
200.     of troom */
201.  mkpos()
202.  {
203.  coord cc,tt;
204.  	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
205.  	if(troom->lx > croom->hx) {
206.  		dx = 1;
207.  		dy = 0;
208.  		xx = croom->hx+1;
209.  		tx = troom->lx-1;
210.  		cc = finddpos(xx,croom->ly,xx,croom->hy);
211.  		tt = finddpos(tx,troom->ly,tx,troom->hy);
212.  	} else if(troom->hy < croom->ly) {
213.  		dy = -1;
214.  		dx = 0;
215.  		yy = croom->ly-1;
216.  		cc = finddpos(croom->lx,yy,croom->hx,yy);
217.  		ty = troom->hy+1;
218.  		tt = finddpos(troom->lx,ty,troom->hx,ty);
219.  	} else if(troom->hx < croom->lx) {
220.  		dx = -1;
221.  		dy = 0;
222.  		xx = croom->lx-1;
223.  		tx = troom->hx+1;
224.  		cc = finddpos(xx,croom->ly,xx,croom->hy);
225.  		tt = finddpos(tx,troom->ly,tx,troom->hy);
226.  	} else {
227.  		dy = 1;
228.  		dx = 0;
229.  		yy = croom->hy+1;
230.  		ty = troom->ly-1;
231.  		cc = finddpos(croom->lx,yy,croom->hx,yy);
232.  		tt = finddpos(troom->lx,ty,troom->hx,ty);
233.  	}
234.  	xx = cc.x;
235.  	yy = cc.y;
236.  	tx = tt.x;
237.  	ty = tt.y;
238.  	if(levl[xx+dx][yy+dy].typ) {
239.  		if(nxcor) newloc();
240.  		else {
241.  			dodoor(xx,yy,croom);
242.  			xx += dx;
243.  			yy += dy;
244.  		}
245.   return;
246.  	}
247.   dodoor(xx,yy,croom);
248.  }
249.  
250.  /* if allowable, create a door at [x,y] */
251.  okdoor(x,y)
252.  register x,y;
253.  {
254.  	if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||
255.  	   levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||
256.  	   levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||
257.  	   levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||
258.  	   (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
259.  	   doorindex >= DOORMAX)
260.  		return(0);
261.  	return(1);
262.  }
263.  
264.  dodoor(x,y,aroom)
265.  register x,y;
266.  register struct mkroom *aroom;
267.  {
268.  	register struct mkroom *broom;
269.  	register tmp;
270.  	if(doorindex >= DOORMAX) panic("DOORMAX exceeded?");
271.  	if(!okdoor(x,y) && nxcor) return;
272.  	if(!rn2(8)) levl[x][y].typ = SDOOR;
273.  	else {
274.  		levl[x][y].scrsym ='+';
275.  		levl[x][y].typ = DOOR;
276.  	}
277.  	aroom->doorct++;
278.  	broom = aroom+1;
279.  	if(broom->hx < 0) tmp = doorindex; else
280.  	for(tmp = doorindex; tmp > broom->fdoor; tmp--)
281.  		doors[tmp] = doors[tmp-1];
282.  	doorindex++;
283.  	doors[tmp].x = x;
284.  	doors[tmp].y = y;
285.  	for( ; broom->hx >= 0; broom++) broom->fdoor++;
286.  }
287.  
288.  newloc()
289.  {
290.  	register a,b;
291.  	register int tryct = 0;
292.  
293.  	++croom;
294.  	++troom;
295.  	if(nxcor || croom->hx < 0 || troom->hx < 0) {
296.  		if(nxcor++ > rn1(nroom,4)) {
297.  			croom = &rooms[nroom];
298.  			return;
299.  		}
300.  		do {
301.  			if(++tryct > 100){
302.  				printf("tryct overflow5\n");
303.  				croom = &rooms[nroom];
304.  				return;
305.  			}
306.  			a = rn2(nroom);
307.  			b = rn2(nroom);
308.  			croom = &rooms[a];
309.  			troom = &rooms[b];
310.  		} while(croom == troom || (troom == croom+1 && !rn2(3)));
311.  	}
312.   mkpos();
313.  }
314.  
315.  /* make a trap somewhere (in croom if mazeflag = 0) */
316.  mktrap(num,mazeflag)
317.  register num,mazeflag;
318.  {
319.  	register struct gen *gtmp;
320.  	register int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0;
321.  	register xchar mx,my;
322.  
323.  	if(!num || num >= TRAPNUM) {
324.  		nopierc = (dlevel < 4) ? 1 : 0;
325.  		nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
326.  		if(index(fut_geno, 'M')) nomimic = 1;
327.  		kind = rn2(TRAPNUM - nopierc - nomimic);
328.  		/* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
329.  	} else kind = num;
330.  
331.  	if(kind == MIMIC) {
332.  		register struct monst *mtmp;
333.  
334.  		fakedoor = (!rn2(3) && !mazeflag);
335.  		fakegold = (!fakedoor && !rn2(2));
336.  		if(fakegold) goldseen = TRUE;
337.  		do {
338.  			if(++tryct > 200) return;
339.  			if(fakedoor) {
340.  				/* note: fakedoor maybe on actual door */
341.  				if(rn2(2)){
342.  					if(rn2(2))
343.  						mx = croom->hx+1;
344.  					else mx = croom->lx-1;
345.  					my = somey();
346.  				} else {
347.  					if(rn2(2))
348.  						my = croom->hy+1;
349.  					else my = croom->ly-1;
350.  					mx = somex();
351.  				}
352.  			} else if(mazeflag) {
353.  				extern coord mazexy();
354.  				coord mm;
355.  				mm = mazexy();
356.  				mx = mm.x;
357.  				my = mm.y;
358.  			} else {
359.  				mx = somex();
360.  				my = somey();
361.  			}
362.  		} while(m_at(mx,my));
363.  		if(mtmp = makemon(PM_MIMIC,mx,my))
364.  		    mtmp->mimic =
365.  			fakegold ? '$' : fakedoor ? '+' :
366.  			(mazeflag && rn2(2)) ? AMULET_SYM :
367.  			"=/)%?![<>" [ rn2(9) ];
368.  		return;
369.  	}
370.  	gtmp = newgen();
371.  	gtmp->gflag = kind;
372.  	do {
373.  		if(++tryct > 200){
374.  			printf("tryct overflow7\n");
375.  			free((char *) gtmp);
376.  			return;
377.  		}
378.  		if(mazeflag){
379.  			extern coord mazexy();
380.  			coord mm;
381.  			mm = mazexy();
382.  			gtmp->gx = mm.x;
383.  			gtmp->gy = mm.y;
384.  		} else {
385.  			gtmp->gx = somex();
386.  			gtmp->gy = somey();
387.  		}
388.  	} while(g_at(gtmp->gx, gtmp->gy, ftrap));
389.  	gtmp->ngen = ftrap;
390.  	ftrap = gtmp;
391.  	if(mazeflag && !rn2(10) && gtmp->gflag < PIERC) gtmp->gflag |= SEEN;
392.  }
393.  
394.  /*VARARGS1*/
395.  panic(str,arg1,arg2,arg3)
396.  char *str,*arg1,*arg2,*arg3;
397.  {
398.  	char bufr[BUFSZ];
399.  	extern char *sprintf();
400.  	(void) sprintf(bufr,str,arg1,arg2,arg3);
401.  	(void) write(1,"\nMKLEV ERROR:  ",15);
402.  	puts(bufr);
403.  	(void) fflush(stdout);
404.  	exit(1);
405.  }
406.  
407.  maker(lowx,ddx,lowy,ddy)
408.  schar lowx,ddx,lowy,ddy;
409.  {
410.  	register x, y, hix = lowx+ddx, hiy = lowy+ddy;
411.  
412.  	if(nroom >= MAXNROFROOMS) return(0);
413.  	if(hix > COLNO-5) hix = COLNO-5;
414.  	if(hiy > ROWNO-4) hiy = ROWNO-4;
415.  chk:
416.  	if(hix <= lowx || hiy <= lowy) return(0);
417.  
418.  	/* check area around room (and make room smaller if necessary) */
419.  	for(x = lowx-4; x <= hix+4; x++)
420.  		for(y = lowy-3; y <= hiy+3; y++)
421.  			if(levl[x][y].typ) {
422.  				if(rn2(3)) return(0);
423.  				lowx = x+5;
424.  				lowy = y+4;
425.  				goto chk;
426.  			}
427.  
428.  	/* on low levels the room is lit (usually) */
429.  	/* secret vaults are always lit */
430.  	if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1))
431.  		for(x = lowx-1; x <= hix+1; x++)
432.  			for(y = lowy-1; y <= hiy+1; y++)
433.  				levl[x][y].lit = 1;
434.  	croom->lx = lowx;
435.  	croom->hx = hix;
436.  	croom->ly = lowy;
437.  	croom->hy = hiy;
438.  	croom->rtype = croom->doorct = croom->fdoor = 0;
439.  	for(x = lowx-1; x <= hix+1; x++)
440.  	    for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
441.  		levl[x][y].scrsym = '-';
442.  		levl[x][y].typ = HWALL;
443.  	}
444.  	for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
445.  	    for(y = lowy; y <= hiy; y++) {
446.  		levl[x][y].scrsym = '|';
447.  		levl[x][y].typ = VWALL;
448.  	}
449.  	for(x = lowx; x <= hix; x++)
450.  	    for(y = lowy; y <= hiy; y++) {
451.  		levl[x][y].scrsym = '.';
452.  		levl[x][y].typ = ROOM;
453.  	}
454.  	croom++;
455.  	croom->hx = -1;
456.  	nroom++;
457.  	return(1);
458.  }
459.  
460.  makecor() {
461.  	register nx, ny;
462.  	register struct rm *crm;
463.  	register dix, diy, secondtry = 0;
464.  
465.  tryagain:
466.  	nx = xx + dx;
467.  	ny = yy + dy;
468.  
469.  	if(nxcor && !rn2(35)) {
470.  		newloc();
471.  		return;
472.  	}
473.  	if(nx == COLNO-1 || nx == 0 || ny == 0 || ny == ROWNO-1) {
474.  		if(nxcor) {
475.  			newloc();
476.  			return;
477.  		} else {
478.  			printf("something went wrong. we try again...\n");
479.  		execl("./mklev",args[0],tfile,tspe,args[3],args[4],args[5],0);
480.  			panic("cannot execute ./mklev\n");
481.  		}
482.  	}
483.  
484.  	dix = abs(nx-tx);
485.  	diy = abs(ny-ty);
486.  	if(dy && dix > diy) {
487.  		dy = 0;
488.  		dx = (nx > tx) ? -1 : 1;
489.  	} else if(dx && diy > dix) {
490.  		dx = 0;
491.  		dy = (ny > ty) ? -1 : 1;
492.  	}
493.  
494.  	crm = &levl[nx][ny];
495.  	if(!(crm->typ)) {
496.  		if(rn2(100)) {
497.  			crm->typ = CORR;
498.  			crm->scrsym = CORR_SYM;
499.  		} else {
500.  			crm->typ = SCORR;
501.  			crm->scrsym = ' ';
502.  		}
503.  		xx = nx;
504.  		yy = ny;
505.  		if(nxcor && !rn2(50)) {
506.  			mkobj_at(ROCK_SYM, nx, ny);
507.  		}
508.   return;
509.  	}
510.  	if(crm->typ == CORR || crm->typ == SCORR) {
511.  		xx = nx;
512.  		yy = ny;
513.  		return;
514.  	}
515.  	if(nx == tx && ny == ty) {
516.  		dodoor(nx,ny,troom);
517.  		newloc();
518.  		return;
519.  	}
520.  	if(!secondtry++ && (nx != xx+dx || ny != yy+dy))
521.  		goto tryagain;
522.  	if(dx) {
523.  		if(ty < ny) dy = -1;
524.  		else dy = levl[nx+dx][ny-1].typ == ROOM?1:-1;
525.  		dx = 0;
526.  	} else {
527.  		if(tx < nx) dx = -1;
528.  		else dx = levl[nx-1][ny+dy].typ == ROOM?1:-1;
529.  		dy = 0;
530.  	}
531.  }
532.  
533.  struct monst *
534.  m_at(x,y)
535.  register x,y;
536.  {
537.  	register struct monst *mtmp;
538.  
539.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
540.  		if(mtmp->mx == x && mtmp->my == y) return(mtmp);
541.  	return(0);
542.  }
543.  
544.  struct gen *
545.  g_at(x,y,ptr)
546.  register x,y;
547.  register struct gen *ptr;
548.  {
549.  	while(ptr) {
550.  		if(ptr->gx == x && ptr->gy == y) return(ptr);
551.  		ptr = ptr->ngen;
552.  	}
553.   return(0);
554.  }