Source:NetHack 3.0.0/mkmaze.c

From NetHackWiki
(Redirected from NetHack 3.0.0/mkmaze.c)
Jump to navigation Jump to search

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

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)mkmaze.c	3.0	88/10/25
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    extern int x_maze_max, y_maze_max;
8.    
9.    #if defined(WALLIFIED_MAZE) || defined(STRONGHOLD)
10.   static int
11.   iswall(x,y)
12.   int x,y;
13.   {
14.   # ifndef WALLIFIED_MAZE
15.   	if (x<0 || y<0 || x>COLNO-1 || y>ROWNO-1)
16.   # else
17.   	if (x<0 || y<0 || x>COLNO || y>ROWNO)
18.   # endif
19.   		return 0;
20.   	return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)
21.   		|| levl[x][y].typ == SDOOR);
22.   }
23.   
24.   void
25.   wallification(x1, y1, x2, y2, see)
26.   int x1, y1, x2, y2;
27.   boolean see;
28.   {
29.   	char type;
30.   	short x,y;
31.   	register struct rm *room;
32.   
33.   	if (x1 < 0) x1 = 0;
34.   	if (x2 < x1) x2 = x1;
35.   	if (x2 > COLNO-1) x2 = COLNO-1;
36.   	if (x1 > x2) x1 = x2;
37.   	if (y1 < 0) y1 = 0;
38.   	if (y2 < y1) y2 = y1;
39.   	if (y2 > COLNO-1) y2 = ROWNO-1;
40.   	if (y1 > y2) y1 = y2;
41.   	for(x = x1; x <= x2; x++)
42.   	    for(y = y1; y <= y2; y++) {
43.   		room = &levl[x][y];
44.   		type = room->typ;
45.   		if (iswall(x,y)) {
46.   		    if (IS_DOOR(type)) {
47.   			room->scrsym = DOOR_SYM;
48.   			continue;
49.   		    } else
50.   		    if (iswall(x,y-1))
51.   			if (iswall(x,y+1))
52.   			    if (iswall(x-1,y))
53.   				if (iswall(x+1,y)) {
54.   					room->scrsym = CRWALL_SYM; /* -+- */
55.   					room->typ = CROSSWALL;
56.   				} else {
57.   					room->scrsym = TLWALL_SYM; /* -| */
58.   					room->typ = TLWALL;
59.   				}
60.   			    else
61.   				if (iswall(x+1,y)) {
62.   					room->scrsym = TRWALL_SYM; /* |- */
63.   					room->typ = TRWALL;
64.   				} else {
65.   					room->typ = VWALL;
66.   #ifdef STRONGHOLD
67.   					if (is_drawbridge_wall(x,y) >= 0)
68.   					    room->scrsym = DB_VWALL_SYM;
69.   					else
70.   #endif
71.   					    room->scrsym = VWALL_SYM; /* | */
72.   				}
73.   			else
74.   			    if (iswall(x-1,y))
75.   				if (iswall(x+1,y)) {		      
76.   					room->scrsym = TUWALL_SYM;  /*  |  */
77.   					room->typ = TUWALL;	    /* -+- */
78.   				} else {
79.   					room->scrsym = BRCORN_SYM;  /*	| */
80.   					room->typ = BRCORNER;	    /* -+ */
81.   				}
82.   			    else
83.   				if (iswall(x+1,y)) {		    
84.   					room->scrsym = BLCORN_SYM;  /* |  */
85.   					room->typ = BLCORNER;	    /* +- */
86.   				} else {
87.   					room->typ = VWALL;
88.   #ifdef STRONGHOLD
89.   					if (is_drawbridge_wall(x,y) >= 0)
90.   					    room->scrsym = DB_VWALL_SYM;
91.   					else
92.   #endif
93.   					    room->scrsym = VWALL_SYM; /* | */
94.   				}
95.   		    else
96.   			if (iswall(x,y+1))
97.   			    if (iswall(x-1,y))
98.   				if (iswall(x+1,y)) {
99.   					room->scrsym = TDWALL_SYM;  /* -+- */
100.  					room->typ = TDWALL;	    /*	| */
101.  				} else {
102.  					room->scrsym = TRCORN_SYM;  /* -+ */
103.  					room->typ = TRCORNER;	    /*	| */
104.  				}
105.  			    else
106.  				if (iswall(x+1,y)) {
107.  					room->scrsym = TLCORN_SYM;  /* +- */
108.  					room->typ = TLCORNER;	    /* |  */
109.  				} else {
110.  					room->typ = VWALL;
111.  #ifdef STRONGHOLD
112.  					if (is_drawbridge_wall(x,y) >= 0)
113.  					    room->scrsym = DB_VWALL_SYM;
114.  					else
115.  #endif
116.  					    room->scrsym = VWALL_SYM; /* | */
117.  				}
118.  			else {
119.  				room->typ = HWALL;
120.  #ifdef STRONGHOLD
121.  				if (is_drawbridge_wall(x,y) >= 0)
122.  				    room->scrsym = DB_HWALL_SYM;
123.  				else
124.  #endif
125.  				    room->scrsym = HWALL_SYM;
126.  			}
127.  		    if (type == SDOOR) room->typ = type;
128.  		    if (see) room->seen = 0;
129.  		} else {
130.  		    switch(room->typ) {
131.  			case STONE:
132.  				room->scrsym = STONE_SYM;
133.  				break;
134.  			case CORR:
135.  				room->scrsym = CORR_SYM;
136.  				break;
137.  			case ROOM:
138.  				room->scrsym = ROOM_SYM;
139.  		    }
140.  		    if (see) room->seen = 0;
141.  		}
142.  	    }
143.  }
144.  #endif /* WALLIFIED_MAZE /**/
145.  
146.  static boolean
147.  okay(x,y,dir)
148.  int x,y;
149.  register int dir;
150.  {
151.  	move(&x,&y,dir);
152.  	move(&x,&y,dir);
153.  	if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0)
154.  		return(FALSE);
155.  	return(TRUE);
156.  }
157.  
158.  static void
159.  maze0xy(cc)	/* find random starting point for maze generation */
160.  	coord	*cc;
161.  {
162.  	cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
163.  	cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
164.  	return;
165.  }
166.  
167.  static const uchar tower[] = {
168.  	MOAT,	  MOAT,     MOAT,     MOAT,	MOAT,	  MOAT,     MOAT,
169.  	MOAT,	  MOAT,     TLCORNER, HWALL,	TRCORNER, MOAT,     MOAT,
170.  	MOAT,	  TLCORNER, BRCORNER, ROOM,	BLCORNER, TRCORNER, MOAT,
171.  	MOAT,	  VWALL,    ROOM,     ROOM,	ROOM,	  VWALL,    MOAT,
172.  	MOAT,	  BLCORNER, TRCORNER, ROOM,	TLCORNER, BRCORNER, MOAT,
173.  	MOAT,	  MOAT,     BLCORNER, HWALL,	BRCORNER, MOAT,     MOAT,
174.  	MOAT,	  MOAT,     MOAT,     MOAT,	MOAT,	  MOAT,     MOAT,
175.  };
176.   
177.  void
178.  makemaz()
179.  {
180.  	int x,y;
181.  	register int zx,zy;
182.  	coord mm;
183.  	int i;
184.  
185.  	is_maze_lev = TRUE;
186.  #ifdef STRONGHOLD
187.  	xdnladder = ydnladder = xupladder = yupladder = 0;
188.  	if (dlevel == stronghold_level) {
189.  		if (load_special("castle")) {
190.  			xupstair = yupstair = 3;
191.  			levl[xupstair][yupstair].scrsym = UP_SYM;
192.  			levl[xupstair][yupstair].typ = STAIRS;
193.  			return;
194.  		}
195.  		impossible("Cannot build the STRONGHOLD!");
196.  	}
197.  	if (dlevel == tower_level) {
198.  		if (load_special("tower1")) {
199.  			xupstair = yupstair = 3;
200.  			levl[xupstair][yupstair].scrsym = UP_SYM;
201.  			levl[xupstair][yupstair].typ = STAIRS;
202.  			return;
203.  		}
204.  		impossible("Cannot build the TOWER!");
205.  	}
206.  	if (dlevel == tower_level+1) {
207.  		if (load_special("tower2")) {
208.  			xupstair = yupstair = 3;
209.  			levl[xupstair][yupstair].scrsym = UP_SYM;
210.  			levl[xupstair][yupstair].typ = STAIRS;
211.  			return;
212.  		}
213.  		impossible("Cannot build the TOWER!");
214.  	}
215.  	if (dlevel == tower_level+2) {
216.  		if (load_special("tower3")) {
217.  			xupstair = yupstair = 3;
218.  			levl[xupstair][yupstair].scrsym = UP_SYM;
219.  			levl[xupstair][yupstair].typ = STAIRS;
220.  			return;
221.  		}
222.  		impossible("Cannot build the TOWER!");
223.  	}
224.  # ifdef ENDGAME
225.  	if (dlevel == ENDLEVEL) {	/* EndGame level */
226.  		if (load_special("endgame")) {
227.  			pline("Well done, mortal!");
228.  			pline("But now thou must face the final Test...");
229.  			pline("Prove thyself worthy or perish!");
230.  			u.ux = x_maze_max - 1;
231.  			u.uy = y_maze_max - 1;
232.  			xupstair = yupstair = 0;
233.  			return;
234.  		}
235.  		impossible("Cannot build the EndGame Level!");
236.  		done("escaped");
237.  	}
238.  # endif
239.  #endif
240.  #ifndef WALLIFIED_MAZE
241.  	for(x = 2; x < x_maze_max; x++)
242.  		for(y = 2; y < y_maze_max; y++)
243.  			levl[x][y].typ = STONE;
244.  #else
245.  	for(x = 2; x <= x_maze_max; x++)
246.  		for(y = 2; y <= y_maze_max; y++)
247.  			levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
248.  #endif
249.  
250.  	/* make decoy wizard levels */
251.  	if((dlevel == wiz_level) ||
252.  #ifdef STRONGHOLD
253.  	   (!rn2(3) && (dlevel > stronghold_level+1))) {
254.  #else
255.  	   (!rn2(3) && (dlevel > medusa_level+1))) {
256.  #endif
257.  
258.  	    register struct monst *mtmp;
259.  
260.  	    zx = x_maze_max / 2;
261.  	    zy = y_maze_max / 2;
262.  	    if (!(zx % 2)) zx++;
263.  	    if (!(zy % 2)) zy++;
264.  	    for(y = zy-3, i=0; y <= zy+3; y++)
265.  		for(x = zx-3; x <= zx+3; x++)
266.  		    levl[x][y].typ = tower[i++];
267.  	    walkfrom(zx+4, zy);
268.  	    if(mtmp = makemon(&mons[PM_HELL_HOUND], zx+1, zy))
269.  		mtmp->msleep = 1;
270.  	    (void) makemon(&mons[PM_KRAKEN], zx+2, zy+2);
271.  	    if (dlevel == wiz_level) {
272.  
273.  		(void) mksobj_at(AMULET_OF_YENDOR, zx, zy);
274.  		flags.made_amulet = 1;
275.  #ifndef STRONGHOLD
276.  		if(mtmp = makemon(&mons[PM_VLAD_THE_IMPALER], zx-1, zy))
277.  			mtmp->msleep = 1;
278.  #endif
279.  		if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], zx, zy))
280.  			mtmp->msleep = 1;
281.  	    } else {
282.  		struct obj *ot;
283.  	    	/* make a cheap plastic imitation */
284.  		if (ot = mksobj_at(AMULET_OF_YENDOR, zx, zy))
285.  		    ot-> spe = -1;
286.  #ifndef STRONGHOLD
287.  		if (mtmp = makemon(&mons[PM_VAMPIRE_LORD], zx-1, zy))
288.  		    mtmp->msleep = 1;
289.  #endif
290.  		(void) makemon(&mons[dprince()], zx, zy);
291.  	    }
292.  	    /* they should wake up when we intrude */
293.  	    (void) maketrap(zx-1, zy, SQBRD);
294.  	    (void) maketrap(zx+1, zy, SQBRD);
295.  	    (void) maketrap(zx, zy-1, SQBRD);
296.  	    (void) maketrap(zx, zy+1, SQBRD);
297.  	} else {
298.  	    maze0xy(&mm);
299.  	    zx = mm.x;
300.  	    zy = mm.y;
301.  	    walkfrom(zx,zy);
302.  #ifndef STRONGHOLD	/* it's in the castle */
303.  # ifdef HARD		/* only one wand of wishing created */
304.  	    if(!rn2(10) || (dlevel == medusa_level + 1))
305.  # endif
306.  		(void) mksobj_at(WAN_WISHING, zx, zy);
307.  #endif
308.  	    (void) mksobj_at(BOULDER, zx, zy);  /* put a boulder on top of it */
309.  	}
310.  
311.  #ifdef WALLIFIED_MAZE
312.  	wallification(2, 2, x_maze_max, y_maze_max, TRUE);
313.  #else
314.  	for(x = 2; x < x_maze_max; x++)
315.  		for(y = 2; y < y_maze_max; y++) {
316.  			switch(levl[x][y].typ) {
317.  			case STONE:
318.  				levl[x][y].scrsym = STONE_SYM;
319.  				break;
320.  			case CORR:
321.  				levl[x][y].scrsym = CORR_SYM;
322.  				break;
323.  			case ROOM:
324.  				levl[x][y].scrsym = ROOM_SYM;
325.  				break;
326.  			case HWALL:
327.  				levl[x][y].scrsym = HWALL_SYM;
328.  				break;
329.  			case VWALL:
330.  				levl[x][y].scrsym = VWALL_SYM;
331.  				break;
332.  			case TLCORNER:
333.  				levl[x][y].scrsym = TLCORN_SYM;
334.  				break;
335.  			case TRCORNER:
336.  				levl[x][y].scrsym = TRCORN_SYM;
337.  				break;
338.  			case BLCORNER:
339.  				levl[x][y].scrsym = BLCORN_SYM;
340.  				break;
341.  			case BRCORNER:
342.  				levl[x][y].scrsym = BRCORN_SYM;
343.  				break;
344.  			}
345.  		}
346.  #endif
347.  	mazexy(&mm);
348.  	levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = UP_SYM;
349.  	levl[xupstair][yupstair].typ = STAIRS;
350.  	xdnstair = ydnstair = 0;
351.  #ifdef STRONGHOLD
352.  	if (dlevel < stronghold_level) {
353.  		mazexy(&mm);
354.  		levl[(xdnstair = mm.x)][(ydnstair = mm.y)].scrsym = DN_SYM;
355.  		levl[xdnstair][ydnstair].typ = STAIRS;
356.  	}
357.  #endif
358.  	for(x = rn1(8,11); x; x--) {
359.  		mazexy(&mm);
360.  		(void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y);
361.  	}
362.  	for(x = rn1(10,2); x; x--) {
363.  		mazexy(&mm);
364.  		(void) mksobj_at(BOULDER, mm.x, mm.y);
365.  	}
366.  	mazexy(&mm);
367.  	(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
368.  	for(x = rn1(5,7); x; x--) {
369.  		mazexy(&mm);
370.  		(void) makemon((struct permonst *) 0, mm.x, mm.y);
371.  	}
372.  	for(x = rn1(6,7); x; x--) {
373.  		mazexy(&mm);
374.  		mkgold(0L,mm.x,mm.y);
375.  	}
376.  	for(x = rn1(6,7); x; x--)
377.  		mktrap(0,1,(struct mkroom *) 0);
378.  }
379.  
380.  #ifdef MSDOS
381.  /* Make the mazewalk iterative by faking a stack.  This is needed to
382.   * ensure the mazewalk is successful in the limited stack space of
383.   * the program.  This iterative version uses the mimumum amount of stack
384.   * that is totally safe.
385.   */
386.  void
387.  walkfrom(x,y)
388.  int x,y;
389.  {
390.  #define CELLS (ROWNO * COLNO) / 4		/* a maze cell is 4 squares */
391.  	char mazex[CELLS + 1], mazey[CELLS + 1];	/* char's are OK */
392.  	int q, a, dir, pos;
393.  	int dirs[4];
394.  
395.  	pos = 1;
396.  	mazex[pos] = (char) x;
397.  	mazey[pos] = (char) y;
398.  	while (pos) {
399.  		x = (int) mazex[pos];
400.  		y = (int) mazey[pos];
401.  #ifndef WALLIFIED_MAZE
402.  		levl[x][y].typ = CORR;
403.  #else
404.  		levl[x][y].typ = ROOM;
405.  #endif
406.  		q = 0;
407.  		for (a = 0; a < 4; a++)
408.  			if(okay(x, y, a)) dirs[q++]= a;
409.  		if (!q)
410.  			pos--;
411.  		else {
412.  			dir = dirs[rn2(q)];
413.  			move(&x, &y, dir);
414.  #ifndef WALLIFIED_MAZE
415.  			levl[x][y].typ = CORR;
416.  #else
417.  			levl[x][y].typ = ROOM;
418.  #endif
419.  			move(&x, &y, dir);
420.  			pos++;
421.  			if (pos > CELLS)
422.  				panic("Overflow in walkfrom");
423.  			mazex[pos] = (char) x;
424.  			mazey[pos] = (char) y;
425.  		}
426.  	}
427.  }
428.  #else
429.  
430.  void
431.  walkfrom(x,y) int x,y; {
432.  register int q,a,dir;
433.  int dirs[4];
434.  #ifndef WALLIFIED_MAZE
435.  	levl[x][y].typ = CORR;
436.  #else
437.  	levl[x][y].typ = ROOM;
438.  #endif
439.  	while(1) {
440.  		q = 0;
441.  		for(a = 0; a < 4; a++)
442.  			if(okay(x,y,a)) dirs[q++]= a;
443.  		if(!q) return;
444.  		dir = dirs[rn2(q)];
445.  		move(&x,&y,dir);
446.  #ifndef WALLIFIED_MAZE
447.  		levl[x][y].typ = CORR;
448.  #else
449.  		levl[x][y].typ = ROOM;
450.  #endif
451.  		move(&x,&y,dir);
452.  		walkfrom(x,y);
453.  	}
454.  }
455.  #endif /* MSDOS */
456.  
457.  void
458.  move(x,y,dir)
459.  register int *x, *y;
460.  register int dir;
461.  {
462.  	switch(dir){
463.  		case 0: --(*y); break;
464.  		case 1: (*x)++; break;
465.  		case 2: (*y)++; break;
466.  		case 3: --(*x); break;
467.  	}
468.  }
469.  
470.  void
471.  mazexy(cc)	/* find random point in generated corridors
472.  		   i.e., don't create items in moats, bunkers, or walls */
473.  	coord	*cc;
474.  {
475.  	int cpt=0;
476.  
477.  	do {
478.  	    cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
479.  	    cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
480.  	    cpt++;
481.  #ifndef WALLIFIED_MAZE
482.  	} while (cpt < 100 && levl[cc->x][cc->y].typ != CORR);
483.  #else
484.  	} while (cpt < 100 && levl[cc->x][cc->y].typ != ROOM);
485.  #endif
486.  	if (cpt >= 100) panic("mazexy: can't find a place!");
487.  	return;
488.  }
489.  
490.  void
491.  bound_digging()
492.  /* put a non-diggable boundary around the initial portion of a level map.
493.   * assumes that no level will initially put things beyond the isok() range.
494.   */
495.  {
496.  	register int x,y;
497.  	register boolean found;
498.  	int xmin,xmax,ymin,ymax;
499.  
500.  	found = FALSE;
501.  	for(xmin=1; !found; xmin++)
502.  		for(y=0; y<=ROWNO-1; y++)
503.  			if(levl[xmin][y].typ != STONE) found = TRUE;
504.  	xmin -= 2;
505.  
506.  	found = FALSE;
507.  	for(xmax=COLNO-2; !found; xmax--)
508.  		for(y=0; y<=ROWNO-1; y++)
509.  			if(levl[xmax][y].typ != STONE) found = TRUE;
510.  	xmax += 2;
511.  
512.  	found = FALSE;
513.  	for(ymin=1; !found; ymin++)
514.  		for(x=xmin; x<=xmax; x++)
515.  			if(levl[x][ymin].typ != STONE) found = TRUE;
516.  	ymin -= 2;
517.  
518.  	found = FALSE;
519.  	for(ymax=ROWNO-2; !found; ymax--)
520.  		for(x=xmin; x<=xmax; x++)
521.  			if(levl[x][ymax].typ != STONE) found = TRUE;
522.  	ymax += 2;
523.  
524.  	for(x=xmin; x<=xmax; x++) {
525.  		levl[x][ymin].diggable = W_NONDIGGABLE;
526.  		levl[x][ymax].diggable = W_NONDIGGABLE;
527.  	}
528.  
529.  	for(y=ymin; y<=ymax; y++) {
530.  		levl[xmin][y].diggable = W_NONDIGGABLE;
531.  		levl[xmax][y].diggable = W_NONDIGGABLE;
532.  	}
533.  }