Source:SLASH'EM 0.0.7E7F2/mklev.c

From NetHackWiki
Revision as of 19:32, 2 October 2006 by Jaytbot (talk | contribs) (Automated source code upload)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to mklev.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/mklev.c#line123]], for example.

The latest source code for vanilla NetHack is at 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: @(#)mklev.c	3.4	2001/11/29	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    /* #define DEBUG */	/* uncomment to enable code debugging */
7.    
8.    #ifdef DEBUG
9.    # ifdef WIZARD
10.   #define debugpline	if (wizard) pline
11.   # else
12.   #define debugpline	pline
13.   # endif
14.   #endif
15.   
16.   /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
17.   /* croom->lx etc are schar (width <= int), so % arith ensures that */
18.   /* conversion of result to int is reasonable */
19.   
20.   
21.   STATIC_DCL void FDECL(mkfount,(int,struct mkroom *));
22.   #ifdef SINKS
23.   STATIC_DCL void FDECL(mksink,(struct mkroom *));
24.   STATIC_DCL void FDECL(mktoilet,(struct mkroom *));
25.   #endif
26.   STATIC_DCL void FDECL(mkaltar,(struct mkroom *));
27.   STATIC_DCL void FDECL(mkgrave,(struct mkroom *));
28.   STATIC_DCL void NDECL(makevtele);
29.   STATIC_DCL void NDECL(clear_level_structures);
30.   STATIC_DCL void NDECL(makelevel);
31.   STATIC_DCL void NDECL(mineralize);
32.   STATIC_DCL boolean FDECL(bydoor,(XCHAR_P,XCHAR_P));
33.   STATIC_DCL struct mkroom *FDECL(find_branch_room, (coord *));
34.   STATIC_DCL struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
35.   STATIC_DCL boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*));
36.   STATIC_DCL void FDECL(makeniche,(int));
37.   STATIC_DCL void NDECL(make_niches);
38.   
39.   STATIC_PTR int FDECL( CFDECLSPEC do_comp,(const genericptr,const genericptr));
40.   
41.   STATIC_DCL void FDECL(dosdoor,(XCHAR_P,XCHAR_P,struct mkroom *,int));
42.   STATIC_DCL void FDECL(join,(int,int,BOOLEAN_P));
43.   STATIC_DCL void FDECL(do_room_or_subroom, (struct mkroom *,int,int,int,int,
44.   				       BOOLEAN_P,SCHAR_P,BOOLEAN_P,BOOLEAN_P));
45.   STATIC_DCL void NDECL(makerooms);
46.   STATIC_DCL void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
47.   STATIC_DCL void FDECL(mkinvpos, (XCHAR_P,XCHAR_P,int));
48.   STATIC_DCL void FDECL(mk_knox_portal, (XCHAR_P,XCHAR_P));
49.   
50.   #define create_vault()	create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
51.   #define init_vault()	vault_x = -1
52.   #define do_vault()	(vault_x != -1)
53.   static xchar		vault_x, vault_y;
54.   boolean goldseen;
55.   static boolean made_branch;	/* used only during level creation */
56.   
57.   /* Args must be (const genericptr) so that qsort will always be happy. */
58.   
59.   STATIC_PTR int CFDECLSPEC
60.   do_comp(vx,vy)
61.   const genericptr vx;
62.   const genericptr vy;
63.   {
64.   #ifdef LINT
65.   /* lint complains about possible pointer alignment problems, but we know
66.      that vx and vy are always properly aligned. Hence, the following
67.      bogus definition:
68.   */
69.   	return (vx == vy) ? 0 : -1;
70.   #else
71.   	register const struct mkroom *x, *y;
72.   
73.   	x = (const struct mkroom *)vx;
74.   	y = (const struct mkroom *)vy;
75.   	if(x->lx < y->lx) return(-1);
76.   	return(x->lx > y->lx);
77.   #endif /* LINT */
78.   }
79.   
80.   STATIC_OVL void
81.   finddpos(cc, xl,yl,xh,yh)
82.   coord *cc;
83.   xchar xl,yl,xh,yh;
84.   {
85.   	register xchar x, y;
86.   
87.   	x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
88.   	y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
89.   	if(okdoor(x, y))
90.   		goto gotit;
91.   
92.   	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
93.   		if(okdoor(x, y))
94.   			goto gotit;
95.   
96.   	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
97.   		if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
98.   			goto gotit;
99.   	/* cannot find something reasonable -- strange */
100.  	x = xl;
101.  	y = yh;
102.  gotit:
103.  	cc->x = x;
104.  	cc->y = y;
105.  	return;
106.  }
107.  
108.  void
109.  sort_rooms()
110.  {
111.  #if defined(SYSV) || defined(DGUX)
112.  	qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), do_comp);
113.  #else
114.  	qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), do_comp);
115.  #endif
116.  }
117.  
118.  STATIC_OVL void
119.  do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
120.      register struct mkroom *croom;
121.      int lowx, lowy;
122.      register int hix, hiy;
123.      boolean lit;
124.      schar rtype;
125.      boolean special;
126.      boolean is_room;
127.  {
128.  	register int x, y;
129.  	struct rm *lev;
130.  
131.  	/* locations might bump level edges in wall-less rooms */
132.  	/* add/subtract 1 to allow for edge locations */
133.  	if(!lowx) lowx++;
134.  	if(!lowy) lowy++;
135.  	if(hix >= COLNO-1) hix = COLNO-2;
136.  	if(hiy >= ROWNO-1) hiy = ROWNO-2;
137.  
138.  	if(lit) {
139.  		for(x = lowx-1; x <= hix+1; x++) {
140.  			lev = &levl[x][max(lowy-1,0)];
141.  			for(y = lowy-1; y <= hiy+1; y++)
142.  				lev++->lit = 1;
143.  		}
144.  		croom->rlit = 1;
145.  	} else
146.  		croom->rlit = 0;
147.  
148.  	croom->lx = lowx;
149.  	croom->hx = hix;
150.  	croom->ly = lowy;
151.  	croom->hy = hiy;
152.  	croom->rtype = rtype;
153.  	croom->doorct = 0;
154.  	/* if we're not making a vault, doorindex will still be 0
155.  	 * if we are, we'll have problems adding niches to the previous room
156.  	 * unless fdoor is at least doorindex
157.  	 */
158.  	croom->fdoor = doorindex;
159.  	croom->irregular = FALSE;
160.  
161.  	croom->nsubrooms = 0;
162.  	croom->sbrooms[0] = (struct mkroom *) 0;
163.  	if (!special) {
164.  	    for(x = lowx-1; x <= hix+1; x++)
165.  		for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
166.  		    levl[x][y].typ = HWALL;
167.  		    levl[x][y].horizontal = 1;	/* For open/secret doors. */
168.  		}
169.  	    for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
170.  		for(y = lowy; y <= hiy; y++) {
171.  		    levl[x][y].typ = VWALL;
172.  		    levl[x][y].horizontal = 0;	/* For open/secret doors. */
173.  		}
174.  	    for(x = lowx; x <= hix; x++) {
175.  		lev = &levl[x][lowy];
176.  		for(y = lowy; y <= hiy; y++)
177.  		    lev++->typ = ROOM;
178.  	    }
179.  	    if (is_room) {
180.  		levl[lowx-1][lowy-1].typ = TLCORNER;
181.  		levl[hix+1][lowy-1].typ = TRCORNER;
182.  		levl[lowx-1][hiy+1].typ = BLCORNER;
183.  		levl[hix+1][hiy+1].typ = BRCORNER;
184.  	    } else {	/* a subroom */
185.  		wallification(lowx-1, lowy-1, hix+1, hiy+1, FALSE);
186.  	    }
187.  	}
188.  }
189.  
190.  
191.  void
192.  add_room(lowx, lowy, hix, hiy, lit, rtype, special)
193.  register int lowx, lowy, hix, hiy;
194.  boolean lit;
195.  schar rtype;
196.  boolean special;
197.  {
198.  	register struct mkroom *croom;
199.  
200.  	croom = &rooms[nroom];
201.  	do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
202.  					    rtype, special, (boolean) TRUE);
203.  	croom++;
204.  	croom->hx = -1;
205.  	nroom++;
206.  }
207.  
208.  void
209.  add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
210.  struct mkroom *proom;
211.  register int lowx, lowy, hix, hiy;
212.  boolean lit;
213.  schar rtype;
214.  boolean special;
215.  {
216.  	register struct mkroom *croom;
217.  
218.  	croom = &subrooms[nsubroom];
219.  	do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
220.  					    rtype, special, (boolean) FALSE);
221.  	proom->sbrooms[proom->nsubrooms++] = croom;
222.  	croom++;
223.  	croom->hx = -1;
224.  	nsubroom++;
225.  }
226.  
227.  STATIC_OVL void
228.  makerooms()
229.  {
230.  	boolean tried_vault = FALSE;
231.  
232.  	/* make rooms until satisfied */
233.  	/* rnd_rect() will returns 0 if no more rects are available... */
234.  	while(nroom < MAXNROFROOMS && rnd_rect()) {
235.  		if(nroom >= (MAXNROFROOMS/6) && rn2(2) && !tried_vault) {
236.  			tried_vault = TRUE;
237.  			if (create_vault()) {
238.  				vault_x = rooms[nroom].lx;
239.  				vault_y = rooms[nroom].ly;
240.  				rooms[nroom].hx = -1;
241.  			}
242.  		} else
243.  		    if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
244.  			return;
245.  	}
246.  	return;
247.  }
248.  
249.  STATIC_OVL void
250.  join(a,b,nxcor)
251.  register int a, b;
252.  boolean nxcor;
253.  {
254.  	coord cc,tt, org, dest;
255.  	register xchar tx, ty, xx, yy;
256.  	register struct mkroom *croom, *troom;
257.  	register int dx, dy;
258.  
259.  	croom = &rooms[a];
260.  	troom = &rooms[b];
261.  
262.  	/* find positions cc and tt for doors in croom and troom
263.  	   and direction for a corridor between them */
264.  
265.  	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
266.  	if(troom->lx > croom->hx) {
267.  		dx = 1;
268.  		dy = 0;
269.  		xx = croom->hx+1;
270.  		tx = troom->lx-1;
271.  		finddpos(&cc, xx, croom->ly, xx, croom->hy);
272.  		finddpos(&tt, tx, troom->ly, tx, troom->hy);
273.  	} else if(troom->hy < croom->ly) {
274.  		dy = -1;
275.  		dx = 0;
276.  		yy = croom->ly-1;
277.  		finddpos(&cc, croom->lx, yy, croom->hx, yy);
278.  		ty = troom->hy+1;
279.  		finddpos(&tt, troom->lx, ty, troom->hx, ty);
280.  	} else if(troom->hx < croom->lx) {
281.  		dx = -1;
282.  		dy = 0;
283.  		xx = croom->lx-1;
284.  		tx = troom->hx+1;
285.  		finddpos(&cc, xx, croom->ly, xx, croom->hy);
286.  		finddpos(&tt, tx, troom->ly, tx, troom->hy);
287.  	} else {
288.  		dy = 1;
289.  		dx = 0;
290.  		yy = croom->hy+1;
291.  		ty = troom->ly-1;
292.  		finddpos(&cc, croom->lx, yy, croom->hx, yy);
293.  		finddpos(&tt, troom->lx, ty, troom->hx, ty);
294.  	}
295.  	xx = cc.x;
296.  	yy = cc.y;
297.  	tx = tt.x - dx;
298.  	ty = tt.y - dy;
299.  	if(nxcor && levl[xx+dx][yy+dy].typ)
300.  		return;
301.  	if (okdoor(xx,yy) || !nxcor)
302.  	    dodoor(xx,yy,croom);
303.  
304.  	org.x  = xx+dx; org.y  = yy+dy;
305.  	dest.x = tx; dest.y = ty;
306.  
307.  	/* KMH -- Support for arboreal levels */
308.  	if (!dig_corridor(&org, &dest, nxcor,
309.  			level.flags.arboreal ? ROOM : CORR, STONE))
310.  	    return;
311.  
312.  	/* we succeeded in digging the corridor */
313.  	if (okdoor(tt.x, tt.y) || !nxcor)
314.  	    dodoor(tt.x, tt.y, troom);
315.  
316.  	if(smeq[a] < smeq[b])
317.  		smeq[b] = smeq[a];
318.  	else
319.  		smeq[a] = smeq[b];
320.  }
321.  
322.  void
323.  makecorridors()
324.  {
325.  	int a, b, i;
326.  	boolean any = TRUE;
327.  
328.  	for(a = 0; a < nroom-1; a++) {
329.  		join(a, a+1, FALSE);
330.  		if(!rn2(50)) break; /* allow some randomness */
331.  	}
332.  	for(a = 0; a < nroom-2; a++)
333.  	    if(smeq[a] != smeq[a+2])
334.  		join(a, a+2, FALSE);
335.  	for(a = 0; any && a < nroom; a++) {
336.  	    any = FALSE;
337.  	    for(b = 0; b < nroom; b++)
338.  		if(smeq[a] != smeq[b]) {
339.  		    join(a, b, FALSE);
340.  		    any = TRUE;
341.  		}
342.  	}
343.  	if(nroom > 2)
344.  	    for(i = rn2(nroom) + 4; i; i--) {
345.  		a = rn2(nroom);
346.  		b = rn2(nroom-2);
347.  		if(b >= a) b += 2;
348.  		join(a, b, TRUE);
349.  	    }
350.  }
351.  
352.  /* ALI - Artifact doors: Track doors in maze levels as well */
353.  
354.  int
355.  add_door(x,y,aroom)
356.  register int x, y;
357.  register struct mkroom *aroom;
358.  {
359.  	register struct mkroom *broom;
360.  	register int tmp;
361.  
362.  	if (doorindex == DOORMAX)
363.  	    return -1;
364.  
365.  	if (aroom) {
366.  	    aroom->doorct++;
367.  	    broom = aroom+1;
368.  	} else
369.  	    /* ALI
370.  	     * Roomless doors must go right at the beginning of the list
371.  	     */
372.  	    broom = &rooms[0];
373.  	if(broom->hx < 0)
374.  	    tmp = doorindex;
375.  	else
376.  	    for(tmp = doorindex; tmp > broom->fdoor; tmp--)
377.  		doors[tmp] = doors[tmp-1];
378.  	doorindex++;
379.  	doors[tmp].x = x;
380.  	doors[tmp].y = y;
381.  	for( ; broom->hx >= 0; broom++) broom->fdoor++;
382.  	doors[tmp].arti_key = 0;
383.  	return tmp;
384.  }
385.  
386.  STATIC_OVL void
387.  dosdoor(x,y,aroom,type)
388.  register xchar x, y;
389.  register struct mkroom *aroom;
390.  register int type;
391.  {
392.  	boolean shdoor = ((*in_rooms(x, y, SHOPBASE))? TRUE : FALSE);
393.  
394.  	if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
395.  		type = DOOR;
396.  	levl[x][y].typ = type;
397.  	if(type == DOOR) {
398.  	    if(!rn2(3)) {      /* is it a locked door, closed, or a doorway? */
399.  		if(!rn2(5))
400.  		    levl[x][y].doormask = D_ISOPEN;
401.  		else if(!rn2(6))
402.  		    levl[x][y].doormask = D_LOCKED;
403.  		else
404.  		    levl[x][y].doormask = D_CLOSED;
405.  
406.  		if (levl[x][y].doormask != D_ISOPEN && !shdoor &&
407.  		    level_difficulty() >= 5 && !rn2(25))
408.  		    levl[x][y].doormask |= D_TRAPPED;
409.  	    } else
410.  #ifdef STUPID
411.  		if (shdoor)
412.  			levl[x][y].doormask = D_ISOPEN;
413.  		else
414.  			levl[x][y].doormask = D_NODOOR;
415.  #else
416.  		levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
417.  #endif
418.  	    if(levl[x][y].doormask & D_TRAPPED) {
419.  		struct monst *mtmp;
420.  
421.  		if (level_difficulty() >= 9 && !rn2(5) &&
422.  		   !((mvitals[PM_SMALL_MIMIC].mvflags & G_GONE) &&
423.  		     (mvitals[PM_LARGE_MIMIC].mvflags & G_GONE) &&
424.  		     (mvitals[PM_GIANT_MIMIC].mvflags & G_GONE))) {
425.  		    /* make a mimic instead */
426.  		    levl[x][y].doormask = D_NODOOR;
427.  		    mtmp = makemon(mkclass(S_MIMIC,0), x, y, NO_MM_FLAGS);
428.  		    if (mtmp)
429.  			set_mimic_sym(mtmp);
430.  		}
431.  	    }
432.  	    /* newsym(x,y); */
433.  	} else { /* SDOOR */
434.  		if(shdoor || !rn2(5))	levl[x][y].doormask = D_LOCKED;
435.  		else			levl[x][y].doormask = D_CLOSED;
436.  
437.  		if(!shdoor && level_difficulty() >= 4 && !rn2(20))
438.  		    levl[x][y].doormask |= D_TRAPPED;
439.  	}
440.  
441.  	add_door(x,y,aroom);
442.  }
443.  
444.  STATIC_OVL boolean
445.  place_niche(aroom,dy,xx,yy)
446.  register struct mkroom *aroom;
447.  int *dy, *xx, *yy;
448.  {
449.  	coord dd;
450.  
451.  	if(rn2(2)) {
452.  	    *dy = 1;
453.  	    finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1);
454.  	} else {
455.  	    *dy = -1;
456.  	    finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1);
457.  	}
458.  	*xx = dd.x;
459.  	*yy = dd.y;
460.  	return((boolean)((isok(*xx,*yy+*dy) && levl[*xx][*yy+*dy].typ == STONE)
461.  	    && (isok(*xx,*yy-*dy) && !IS_POOL(levl[*xx][*yy-*dy].typ)
462.  				  && !IS_FURNITURE(levl[*xx][*yy-*dy].typ))));
463.  }
464.  
465.  /* there should be one of these per trap, in the same order as trap.h */
466.  static NEARDATA const char *trap_engravings[TRAPNUM] = {
467.  			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
468.  			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
469.  			(char *)0, (char *)0, (char *)0, (char *)0,
470.  			/* 14..16: trap door, teleport, level-teleport */
471.  			"Vlad was here", "ad aerarium", "ad aerarium",
472.  			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
473.  			(char *)0,
474.  };
475.  
476.  STATIC_OVL void
477.  makeniche(trap_type)
478.  int trap_type;
479.  {
480.  	register struct mkroom *aroom;
481.  	register struct rm *rm;
482.  	register int vct = 8;
483.  	int dy, xx, yy;
484.  	register struct trap *ttmp;
485.  
486.  	if(doorindex < DOORMAX)
487.  	  while(vct--) {
488.  	    aroom = &rooms[rn2(nroom)];
489.  	    if(aroom->rtype != OROOM) continue;	/* not an ordinary room */
490.  	    if(aroom->doorct == 1 && rn2(5)) continue;
491.  	    if(!place_niche(aroom,&dy,&xx,&yy)) continue;
492.  
493.  	    rm = &levl[xx][yy+dy];
494.  	    if(trap_type || !rn2(4)) {
495.  
496.  		rm->typ = SCORR;
497.  		if(trap_type) {
498.  		    if((trap_type == HOLE || trap_type == TRAPDOOR)
499.  			&& !Can_fall_thru(&u.uz))
500.  			trap_type = ROCKTRAP;
501.  		    ttmp = maketrap(xx, yy+dy, trap_type);
502.  		    if (ttmp) {
503.  			if (trap_type != ROCKTRAP) ttmp->once = 1;
504.  			if (trap_engravings[trap_type]) {
505.  			    make_engr_at(xx, yy-dy,
506.  				     trap_engravings[trap_type], 0L, DUST);
507.  			    wipe_engr_at(xx, yy-dy, 5); /* age it a little */
508.  			}
509.  		    }
510.  		}
511.  		dosdoor(xx, yy, aroom, SDOOR);
512.  	    } else {
513.  		rm->typ = CORR;
514.  		if(rn2(7))
515.  		    dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
516.  		else {
517.  		    if (!level.flags.noteleport)
518.  			(void) mksobj_at(SCR_TELEPORTATION,
519.  					 xx, yy+dy, TRUE, FALSE);
520.  		    if (!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE);
521.  		}
522.  	    }
523.  	    return;
524.  	}
525.  }
526.  
527.  STATIC_OVL void
528.  make_niches()
529.  {
530.  	register int ct = rnd((nroom>>1) + 1), dep = depth(&u.uz);
531.  
532.  	boolean	ltptr = (!level.flags.noteleport && dep > 15),
533.  		vamp = (dep > 5 && dep < 25);
534.  
535.  	while(ct--) {
536.  		if (ltptr && !rn2(6)) {
537.  			ltptr = FALSE;
538.  			makeniche(LEVEL_TELEP);
539.  		} else if (vamp && !rn2(6)) {
540.  			vamp = FALSE;
541.  			makeniche(TRAPDOOR);
542.  		} else	makeniche(NO_TRAP);
543.  	}
544.  }
545.  
546.  STATIC_OVL void
547.  makevtele()
548.  {
549.  	makeniche(TELEP_TRAP);
550.  }
551.  
552.  /* clear out various globals that keep information on the current level.
553.   * some of this is only necessary for some types of levels (maze, normal,
554.   * special) but it's easier to put it all in one place than make sure
555.   * each type initializes what it needs to separately.
556.   */
557.  STATIC_OVL void
558.  clear_level_structures()
559.  {
560.  #ifdef DISPLAY_LAYERS
561.  	static struct rm zerorm = { S_stone, 0, 0, 0, 0, 0,
562.  #else
563.  	static struct rm zerorm = { cmap_to_glyph(S_stone),
564.  #endif
565.  						0, 0, 0, 0, 0, 0, 0, 0 };
566.  	register int x,y;
567.  	register struct rm *lev;
568.  
569.  	for(x=0; x<COLNO; x++) {
570.  	    lev = &levl[x][0];
571.  	    for(y=0; y<ROWNO; y++) {
572.  		*lev++ = zerorm;
573.  #ifdef MICROPORT_BUG
574.  		level.objects[x][y] = (struct obj *)0;
575.  		level.monsters[x][y] = (struct monst *)0;
576.  #endif
577.  	    }
578.  	}
579.  #ifndef MICROPORT_BUG
580.  	(void) memset((genericptr_t)level.objects, 0, sizeof(level.objects));
581.  	(void) memset((genericptr_t)level.monsters, 0, sizeof(level.monsters));
582.  #endif
583.  	level.objlist = (struct obj *)0;
584.  	level.buriedobjlist = (struct obj *)0;
585.  	level.monlist = (struct monst *)0;
586.  	level.damagelist = (struct damage *)0;
587.  
588.  	level.flags.nfountains = 0;
589.  	level.flags.nsinks = 0;
590.  	level.flags.has_shop = 0;
591.  	level.flags.has_vault = 0;
592.  	level.flags.has_zoo = 0;
593.  	level.flags.has_court = 0;
594.  	level.flags.has_morgue = level.flags.graveyard = 0;
595.  	level.flags.has_beehive = 0;
596.  	level.flags.has_barracks = 0;
597.  	level.flags.has_lemurepit = 0;
598.  	level.flags.has_migohive = 0;
599.  	level.flags.has_fungusfarm = 0;
600.  	level.flags.has_temple = 0;
601.  	level.flags.has_swamp = 0;
602.  	level.flags.noteleport = 0;
603.  	level.flags.hardfloor = 0;
604.  	level.flags.nommap = 0;
605.  	level.flags.hero_memory = 1;
606.  	level.flags.shortsighted = 0;
607.  	level.flags.arboreal = 0;
608.  	level.flags.is_maze_lev = 0;
609.  	level.flags.is_cavernous_lev = 0;
610.  	/* KMH -- more level properties */
611.  	level.flags.arboreal = 0;
612.  
613.  	/* [DS] - Michael Clarke's Lethe flag */
614.  	level.flags.lethe = 0;
615.  
616.  	nroom = 0;
617.  	rooms[0].hx = -1;
618.  	nsubroom = 0;
619.  	subrooms[0].hx = -1;
620.  	doorindex = 0;
621.  	init_rect();
622.  	init_vault();
623.  	xdnstair = ydnstair = xupstair = yupstair = 0;
624.  	sstairs.sx = sstairs.sy = 0;
625.  	xdnladder = ydnladder = xupladder = yupladder = 0;
626.  	made_branch = FALSE;
627.  	clear_regions();
628.  }
629.  
630.  STATIC_OVL void
631.  makelevel()
632.  {
633.  	register struct mkroom *croom, *troom;
634.  	register int tryct;
635.  	register int x, y;
636.  	struct monst *tmonst;	/* always put a web with a spider */
637.  	branch *branchp;
638.  	int room_threshold;
639.  
640.  	if(wiz1_level.dlevel == 0) init_dungeons();
641.  	oinit();	/* assign level dependent obj probabilities */
642.  	clear_level_structures();
643.  
644.  	{
645.  	    register s_level *slev = Is_special(&u.uz);
646.  
647.  	    /* check for special levels */
648.  #ifdef REINCARNATION
649.  	    if (slev && !Is_rogue_level(&u.uz))
650.  #else
651.  	    if (slev)
652.  #endif
653.  	    {
654.  		    makemaz(slev->proto);
655.  		    return;
656.  	    } else if (dungeons[u.uz.dnum].proto[0]) {
657.  		    makemaz("");
658.  		    return;
659.  	    } else if (In_mines(&u.uz)) {
660.  		    makemaz("minefill");
661.  		    return;
662.  	    } else if (In_quest(&u.uz)) {
663.  		    char        fillname[16];
664.  		    s_level	*loc_lev;
665.  
666.  		    Sprintf(fillname, "%s-loca", urole.filecode);
667.  		    loc_lev = find_level(fillname);
668.  
669.  		    Sprintf(fillname, "%s-fil", urole.filecode);
670.  		    Strcat(fillname,
671.  			   (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
672.  		    makemaz(fillname);
673.  		    return;
674.  	    } else if(In_hell(&u.uz) ||
675.  		  (rn2(5) && u.uz.dnum == medusa_level.dnum
676.  			  && depth(&u.uz) > depth(&medusa_level))) {
677.  		    makemaz("");
678.  		    return;
679.  	    }
680.  	}
681.  
682.  	/* otherwise, fall through - it's a "regular" level. */
683.  
684.  #ifdef REINCARNATION
685.  	if (Is_rogue_level(&u.uz)) {
686.  		makeroguerooms();
687.  		makerogueghost();
688.  	} else
689.  #endif
690.  		makerooms();
691.  	sort_rooms();
692.  
693.  	/* construct stairs (up and down in different rooms if possible) */
694.  	croom = &rooms[rn2(nroom)];
695.  	if (!Is_botlevel(&u.uz))
696.  	     mkstairs(somex(croom), somey(croom), 0, croom);	/* down */
697.  	if (nroom > 1) {
698.  	    troom = croom;
699.  	    croom = &rooms[rn2(nroom-1)];
700.  	    if (croom == troom) croom++;
701.  	}
702.  
703.  	if (u.uz.dlevel != 1) {
704.  	    xchar sx, sy;
705.  	    do {
706.  		sx = somex(croom);
707.  		sy = somey(croom);
708.  	    } while(occupied(sx, sy));
709.  	    mkstairs(sx, sy, 1, croom);	/* up */
710.  	}
711.  
712.  	branchp = Is_branchlev(&u.uz);	/* possible dungeon branch */
713.  	room_threshold = branchp ? 4 : 3; /* minimum number of rooms needed
714.  					     to allow a random special room */
715.  #ifdef REINCARNATION
716.  	if (Is_rogue_level(&u.uz)) goto skip0;
717.  #endif
718.  	makecorridors();
719.  	make_niches();
720.  
721.  	/* make a secret treasure vault, not connected to the rest */
722.  	if(do_vault()) {
723.  		xchar w,h;
724.  #ifdef DEBUG
725.  		debugpline("trying to make a vault...");
726.  #endif
727.  		w = 1;
728.  		h = 1;
729.  		if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
730.  		    fill_vault:
731.  			add_room(vault_x, vault_y, vault_x+w,
732.  				 vault_y+h, TRUE, VAULT, FALSE);
733.  			level.flags.has_vault = 1;
734.  			++room_threshold;
735.  			fill_room(&rooms[nroom - 1], FALSE);
736.  			mk_knox_portal(vault_x+w, vault_y+h);
737.  			if(!level.flags.noteleport && !rn2(3)) makevtele();
738.  		} else if(rnd_rect() && create_vault()) {
739.  			vault_x = rooms[nroom].lx;
740.  			vault_y = rooms[nroom].ly;
741.  			if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
742.  				goto fill_vault;
743.  			else
744.  				rooms[nroom].hx = -1;
745.  		}
746.  	}
747.  
748.      {
749.  	register int u_depth = depth(&u.uz);
750.  
751.  #ifdef WIZARD
752.  	if(wizard && nh_getenv("SHOPTYPE")) mkroom(SHOPBASE); else
753.  #endif
754.  	if (u_depth > 1 &&
755.  	    u_depth < depth(&medusa_level) &&
756.  	    nroom >= room_threshold &&
757.  	    rn2(u_depth) < 3) mkroom(SHOPBASE);
758.   
759.  	/* [Tom] totally reorganized this into categories... used
760.  	   to be only one special room on a level... now allows
761.  	   one of each major type */
762.  	else {
763.  	    /* courtrooms & barracks */
764.  	    if(depth(&u.uz) > 4 && !rn2(12)) mkroom(COURT);
765.  	else if (u_depth > 5 && !rn2(8) &&
766.  	   !(mvitals[PM_LEPRECHAUN].mvflags & G_GONE)) mkroom(LEPREHALL);
767.  	    else if(depth(&u.uz) > 14 && !rn2(12)) mkroom(GIANTCOURT);
768.  	    else if(depth(&u.uz) > 14 && !rn2(7) &&
769.  		(mvitals[PM_SOLDIER].mvflags & G_GONE)) mkroom(BARRACKS);
770.  	
771.  	    /* hives */
772.  	    if(depth(&u.uz) > 9 && !rn2(12) &&
773.  		(mvitals[PM_KILLER_BEE].mvflags & G_GONE)) mkroom(BEEHIVE);
774.  	else if (u_depth > 12 && !rn2(8)) mkroom(ANTHOLE);
775.  
776.  	    /* zoos */
777.  	    if(depth(&u.uz) > 6 && !rn2(12)) mkroom(ZOO);
778.  	    /* fungus farms are rare... */
779.  	    else if (u_depth > 7 && !rn2(25)) mkroom(FUNGUSFARM);
780.  	    else if(depth(&u.uz) > 9 && !rn2(15)) mkroom(REALZOO);
781.  
782.  	    /* neat rooms */
783.  	    if(depth(&u.uz) > 8 && !rn2(13)) mkroom(TEMPLE);
784.  	    else if(depth(&u.uz) > 11 && !rn2(14)) mkroom(MORGUE);
785.  	    else if(depth(&u.uz) > 13 && !rn2(15)) mkroom(BADFOODSHOP);
786.  	    else if(depth(&u.uz) > 18 && !rn2(7)) mkroom(SWAMP);
787.  
788.  	    /* dangerous ones */
789.  	    if (u_depth > 16 && !rn2(8) &&
790.  	   !(mvitals[PM_COCKATRICE].mvflags & G_GONE)) mkroom(COCKNEST);
791.  	    else if(depth(&u.uz) > 20 && !rn2(20)) mkroom(DRAGONLAIR);
792.  	    else if (u_depth > 25 && !rn2(20) && 
793.  		!(mvitals[PM_MIGO_DRONE].mvflags & G_GONE)) mkroom(MIGOHIVE);
794.  	    /* [DS] the restriction of lemure pits to Gehennom means they're
795.  	     *      never going to show up randomly (no random room+corridor
796.  	     *      levels in Gehennom). Perhaps this should be removed? */
797.  	    else if (In_hell(&u.uz) && !rn2(12) &&
798.  		!(mvitals[PM_LEMURE].mvflags & G_GONE)) mkroom(LEMUREPIT);
799.      }
800.  
801.  #ifdef REINCARNATION
802.  skip0:
803.  #endif
804.  	/* Place multi-dungeon branch. */
805.  	place_branch(branchp, 0, 0);
806.  
807.  	/* for each room: put things inside */
808.  	for(croom = rooms; croom->hx > 0; croom++) {
809.  		if(croom->rtype != OROOM) continue;
810.  
811.  		/* put a sleeping monster inside */
812.  		/* Note: monster may be on the stairs. This cannot be
813.  		   avoided: maybe the player fell through a trap door
814.  		   while a monster was on the stairs. Conclusion:
815.  		   we have to check for monsters on the stairs anyway. */
816.  		if(u.uhave.amulet || !rn2(3)) {
817.  		    x = somex(croom); y = somey(croom);
818.  		    tmonst = makemon((struct permonst *) 0, x,y,NO_MM_FLAGS);
819.  		    if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER] &&
820.  			    !occupied(x, y))
821.  			(void) maketrap(x, y, WEB);
822.  		}
823.  		/* put traps and mimics inside */
824.  		goldseen = FALSE;
825.  		x = 8 - (level_difficulty()/6);
826.  		if (x <= 1) x = 2;
827.  		while (!rn2(x))
828.  		    mktrap(0,0,croom,(coord*)0);
829.  		if (!goldseen && !rn2(3))
830.  		    (void) mkgold(0L, somex(croom), somey(croom));
831.  #ifdef REINCARNATION
832.  		x = 80 - (depth(&u.uz) * 2);
833.  		if (x < 2) x = 2;
834.  		if(!rn2(x)) mkgrave(croom);
835.  
836.  		if(Is_rogue_level(&u.uz)) goto skip_nonrogue;
837.  #endif
838.  		if(!rn2(10)) mkfount(0,croom);
839.  #ifdef SINKS
840.  		if(!rn2(60)) {
841.  		    mksink(croom);
842.  		    if(!rn2(3)) mktoilet(croom);
843.  		}
844.  #endif
845.  		x = 80 - (depth(&u.uz) * 2);
846.  		if (x < 2) x = 2;
847.  		if(!rn2(x)) mkgrave(croom);
848.  		if(!rn2(60)) mkaltar(croom);
849.  
850.  		/* put statues inside */
851.  		if(!rn2(20))
852.  		    (void) mkcorpstat(STATUE, (struct monst *)0,
853.  				      (struct permonst *)0,
854.  				      somex(croom), somey(croom), TRUE);
855.  		/* put box/chest inside;
856.  		 *  40% chance for at least 1 box, regardless of number
857.  		 *  of rooms; about 5 - 7.5% for 2 boxes, least likely
858.  		 *  when few rooms; chance for 3 or more is neglible.
859.  		 */
860.  		if(!rn2(nroom * 5 / 2))
861.  		    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
862.  				     somex(croom), somey(croom), TRUE, FALSE);
863.  
864.  		/* maybe make some graffiti */
865.  		if(!rn2(27 + 3 * abs(depth(&u.uz)))) {
866.  		    char buf[BUFSZ];
867.  		    const char *mesg = random_engraving(buf);
868.  		    if (mesg) {
869.  			do {
870.  			    x = somex(croom);  y = somey(croom);
871.  			} while(levl[x][y].typ != ROOM && !rn2(40));
872.  			if (!(IS_POOL(levl[x][y].typ) ||
873.  			      IS_FURNITURE(levl[x][y].typ)))
874.  			    make_engr_at(x, y, mesg, 0L, MARK);
875.  		    }
876.  		}
877.  
878.  #ifdef REINCARNATION
879.  	skip_nonrogue:
880.  #endif
881.  
882.  /* STEPHEN WHITE'S NEW CODE */
883.  		if(!rn2(5)) {
884.  		    (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
885.  		    tryct = 0;
886.  		    while(!rn2(4)) {
887.  			if(++tryct > 100) {
888.  			    impossible("tryct overflow4");
889.  			    break;
890.  			}
891.  			(void) mkobj_at(0, somex(croom), somey(croom), TRUE);
892.  		    }
893.  		}
894.  	}
895.     }
896.  }
897.  
898.  /*
899.   *	Place deposits of minerals (gold and misc gems) in the stone
900.   *	surrounding the rooms on the map.
901.   *	Also place kelp in water.
902.   */
903.  
904.  STATIC_OVL void
905.  mineralize()
906.  {
907.  	s_level *sp;
908.  	struct obj *otmp;
909.  	int goldprob, gemprob, x, y, cnt;
910.  
911.  
912.  	/* Place kelp, except on the plane of water */
913.  	if (In_endgame(&u.uz)) return;
914.  	for (x = 2; x < (COLNO - 2); x++)
915.  	    for (y = 1; y < (ROWNO - 1); y++)
916.  		if ((levl[x][y].typ == POOL && !rn2(10)) ||
917.  			(levl[x][y].typ == MOAT && !rn2(30)))
918.  	    	    (void)mksobj_at(KELP_FROND, x, y, TRUE, FALSE);
919.  
920.  	/* determine if it is even allowed;
921.  	   almost all special levels are excluded */
922.  	if (In_hell(&u.uz) || In_V_tower(&u.uz) ||
923.  #ifdef REINCARNATION
924.  		Is_rogue_level(&u.uz) ||
925.  #endif
926.  		level.flags.arboreal ||
927.  		((sp = Is_special(&u.uz)) != 0 && !Is_oracle_level(&u.uz)
928.  					&& (!In_mines(&u.uz) || sp->flags.town)
929.  	    )) return;
930.  
931.  	/* basic level-related probabilities */
932.  	goldprob = 20 + depth(&u.uz) / 3;
933.  	gemprob = goldprob / 4;
934.  
935.  	/* mines have ***MORE*** goodies - otherwise why mine? */
936.  	if (In_mines(&u.uz)) {
937.  	    goldprob *= 2;
938.  	    gemprob *= 3;
939.  	} else if (In_quest(&u.uz)) {
940.  	    goldprob /= 4;
941.  	    gemprob /= 6;
942.  	}
943.  
944.  	/*
945.  	 * Seed rock areas with gold and/or gems.
946.  	 * We use fairly low level object handling to avoid unnecessary
947.  	 * overhead from placing things in the floor chain prior to burial.
948.  	 */
949.  	for (x = 2; x < (COLNO - 2); x++)
950.  	  for (y = 1; y < (ROWNO - 1); y++)
951.  	    if (levl[x][y+1].typ != STONE) {	 /* <x,y> spot not eligible */
952.  		y += 2;		/* next two spots aren't eligible either */
953.  	    } else if (levl[x][y].typ != STONE) { /* this spot not eligible */
954.  		y += 1;		/* next spot isn't eligible either */
955.  	    } else if (!(levl[x][y].wall_info & W_NONDIGGABLE) &&
956.  		  levl[x][y-1].typ   == STONE &&
957.  		  levl[x+1][y-1].typ == STONE && levl[x-1][y-1].typ == STONE &&
958.  		  levl[x+1][y].typ   == STONE && levl[x-1][y].typ   == STONE &&
959.  		  levl[x+1][y+1].typ == STONE && levl[x-1][y+1].typ == STONE) {
960.  		if (rn2(1000) < goldprob) {
961.  		    if ((otmp = mksobj(GOLD_PIECE, FALSE, FALSE)) != 0) {
962.  			otmp->ox = x,  otmp->oy = y;
963.  			otmp->quan = 1L + rnd(goldprob * 3);
964.  			otmp->owt = weight(otmp);
965.  			if (!rn2(3)) add_to_buried(otmp);
966.  			else place_object(otmp, x, y);
967.  		    }
968.  		}
969.  		if (rn2(1000) < gemprob) {
970.  		    for (cnt = rnd(2 + dunlev(&u.uz) / 3); cnt > 0; cnt--)
971.  			if ((otmp = mkobj(GEM_CLASS, FALSE)) != 0) {
972.  			    if (otmp->otyp == ROCK) {
973.  				dealloc_obj(otmp);	/* discard it */
974.  			    } else {
975.  				otmp->ox = x,  otmp->oy = y;
976.  				if (!rn2(3)) add_to_buried(otmp);
977.  				else place_object(otmp, x, y);
978.  			    }
979.  		    }
980.  		}
981.  	    }
982.  }
983.  
984.  void
985.  mklev()
986.  {
987.  	struct mkroom *croom;
988.  
989.  	if(getbones()) return;
990.  	in_mklev = TRUE;
991.  	makelevel();
992.  	bound_digging();
993.  	mineralize();
994.  	in_mklev = FALSE;
995.  	/* has_morgue gets cleared once morgue is entered; graveyard stays
996.  	   set (graveyard might already be set even when has_morgue is clear
997.  	   [see fixup_special()], so don't update it unconditionally) */
998.  	if (level.flags.has_morgue)
999.  	    level.flags.graveyard = 1;
1000. 	if(!level.flags.is_maze_lev) {
1001. 	    for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
1002. #ifdef SPECIALIZATION
1003. 		topologize(croom, FALSE);
1004. #else
1005. 		topologize(croom);
1006. #endif
1007. 	}
1008. 	set_wall_state();
1009. }
1010. 
1011. void
1012. #ifdef SPECIALIZATION
1013. topologize(croom, do_ordinary)
1014. register struct mkroom *croom;
1015. boolean do_ordinary;
1016. #else
1017. topologize(croom)
1018. register struct mkroom *croom;
1019. #endif
1020. {
1021. 	register int x, y, roomno = (croom - rooms) + ROOMOFFSET;
1022. 	register int lowx = croom->lx, lowy = croom->ly;
1023. 	register int hix = croom->hx, hiy = croom->hy;
1024. #ifdef SPECIALIZATION
1025. 	register schar rtype = croom->rtype;
1026. #endif
1027. 	register int subindex, nsubrooms = croom->nsubrooms;
1028. 
1029. 	/* skip the room if already done; i.e. a shop handled out of order */
1030. 	/* also skip if this is non-rectangular (it _must_ be done already) */
1031. 	if ((int) levl[lowx][lowy].roomno == roomno || croom->irregular)
1032. 	    return;
1033. #ifdef SPECIALIZATION
1034. # ifdef REINCARNATION
1035. 	if (Is_rogue_level(&u.uz))
1036. 	    do_ordinary = TRUE;		/* vision routine helper */
1037. # endif
1038. 	if ((rtype != OROOM) || do_ordinary)
1039. #endif
1040. 	{
1041. 	    /* do innards first */
1042. 	    for(x = lowx; x <= hix; x++)
1043. 		for(y = lowy; y <= hiy; y++)
1044. #ifdef SPECIALIZATION
1045. 		    if (rtype == OROOM)
1046. 			levl[x][y].roomno = NO_ROOM;
1047. 		    else
1048. #endif
1049. 			levl[x][y].roomno = roomno;
1050. 	    /* top and bottom edges */
1051. 	    for(x = lowx-1; x <= hix+1; x++)
1052. 		for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
1053. 		    levl[x][y].edge = 1;
1054. 		    if (levl[x][y].roomno)
1055. 			levl[x][y].roomno = SHARED;
1056. 		    else
1057. 			levl[x][y].roomno = roomno;
1058. 		}
1059. 	    /* sides */
1060. 	    for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
1061. 		for(y = lowy; y <= hiy; y++) {
1062. 		    levl[x][y].edge = 1;
1063. 		    if (levl[x][y].roomno)
1064. 			levl[x][y].roomno = SHARED;
1065. 		    else
1066. 			levl[x][y].roomno = roomno;
1067. 		}
1068. 	}
1069. 	/* subrooms */
1070. 	for (subindex = 0; subindex < nsubrooms; subindex++)
1071. #ifdef SPECIALIZATION
1072. 		topologize(croom->sbrooms[subindex], (rtype != OROOM));
1073. #else
1074. 		topologize(croom->sbrooms[subindex]);
1075. #endif
1076. }
1077. 
1078. /* Find an unused room for a branch location. */
1079. STATIC_OVL struct mkroom *
1080. find_branch_room(mp)
1081.     coord *mp;
1082. {
1083.     struct mkroom *croom = 0;
1084. 
1085.     if (nroom == 0) {
1086. 	mazexy(mp);		/* already verifies location */
1087.     } else {
1088. 	/* not perfect - there may be only one stairway */
1089. 	if(nroom > 2) {
1090. 	    int tryct = 0;
1091. 
1092. 	    do
1093. 		croom = &rooms[rn2(nroom)];
1094. 	    while((croom == dnstairs_room || croom == upstairs_room ||
1095. 		  croom->rtype != OROOM) && (++tryct < 100));
1096. 	} else
1097. 	    croom = &rooms[rn2(nroom)];
1098. 
1099. 	do {
1100. 	    if (!somexy(croom, mp))
1101. 		impossible("Can't place branch!");
1102. 	} while(occupied(mp->x, mp->y) ||
1103. 	    (levl[mp->x][mp->y].typ != CORR && levl[mp->x][mp->y].typ != ROOM));
1104.     }
1105.     return croom;
1106. }
1107. 
1108. /* Find the room for (x,y).  Return null if not in a room. */
1109. STATIC_OVL struct mkroom *
1110. pos_to_room(x, y)
1111.     xchar x, y;
1112. {
1113.     int i;
1114.     struct mkroom *curr;
1115. 
1116.     for (curr = rooms, i = 0; i < nroom; curr++, i++)
1117. 	if (inside_room(curr, x, y)) return curr;;
1118.     return (struct mkroom *) 0;
1119. }
1120. 
1121. 
1122. /* If given a branch, randomly place a special stair or portal. */
1123. void
1124. place_branch(br, x, y)
1125. branch *br;	/* branch to place */
1126. xchar x, y;	/* location */
1127. {
1128. 	coord	      m;
1129. 	d_level	      *dest;
1130. 	boolean	      make_stairs;
1131. 	struct mkroom *br_room;
1132. 
1133. 	/*
1134. 	 * Return immediately if there is no branch to make or we have
1135. 	 * already made one.  This routine can be called twice when
1136. 	 * a special level is loaded that specifies an SSTAIR location
1137. 	 * as a favored spot for a branch.
1138. 	 */
1139. 	if (!br || made_branch) return;
1140. 
1141. 	if (!x) {	/* find random coordinates for branch */
1142. 	    br_room = find_branch_room(&m);
1143. 	    x = m.x;
1144. 	    y = m.y;
1145. 	} else {
1146. 	    br_room = pos_to_room(x, y);
1147. 	}
1148. 
1149. 	if (on_level(&br->end1, &u.uz)) {
1150. 	    /* we're on end1 */
1151. 	    make_stairs = br->type != BR_NO_END1;
1152. 	    dest = &br->end2;
1153. 	} else {
1154. 	    /* we're on end2 */
1155. 	    make_stairs = br->type != BR_NO_END2;
1156. 	    dest = &br->end1;
1157. 	}
1158. 
1159. 	if (br->type == BR_PORTAL) {
1160. 	    mkportal(x, y, dest->dnum, dest->dlevel);
1161. 	} else if (make_stairs) {
1162. 	    sstairs.sx = x;
1163. 	    sstairs.sy = y;
1164. 	    sstairs.up = (char) on_level(&br->end1, &u.uz) ?
1165. 					    br->end1_up : !br->end1_up;
1166. 	    assign_level(&sstairs.tolev, dest);
1167. 	    sstairs_room = br_room;
1168. 
1169. 	    levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
1170. 	    levl[x][y].typ = STAIRS;
1171. 	}
1172. 	/*
1173. 	 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
1174. 	 * make_stairs is false) since there is currently only one branch
1175. 	 * per level, if we failed once, we're going to fail again on the
1176. 	 * next call.
1177. 	 */
1178. 	made_branch = TRUE;
1179. }
1180. 
1181. STATIC_OVL boolean
1182. bydoor(x, y)
1183. register xchar x, y;
1184. {
1185. 	register int typ;
1186. 
1187. 	if (isok(x+1, y)) {
1188. 		typ = levl[x+1][y].typ;
1189. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
1190. 	}
1191. 	if (isok(x-1, y)) {
1192. 		typ = levl[x-1][y].typ;
1193. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
1194. 	}
1195. 	if (isok(x, y+1)) {
1196. 		typ = levl[x][y+1].typ;
1197. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
1198. 	}
1199. 	if (isok(x, y-1)) {
1200. 		typ = levl[x][y-1].typ;
1201. 		if (IS_DOOR(typ) || typ == SDOOR) return TRUE;
1202. 	}
1203. 	return FALSE;
1204. }
1205. 
1206. /* see whether it is allowable to create a door at [x,y] */
1207. int
1208. okdoor(x,y)
1209. register xchar x, y;
1210. {
1211. 	register boolean near_door = bydoor(x, y);
1212. 
1213. 	return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&
1214. 			doorindex < DOORMAX && !near_door);
1215. }
1216. 
1217. void
1218. dodoor(x,y,aroom)
1219. register int x, y;
1220. register struct mkroom *aroom;
1221. {
1222. 	if(doorindex >= DOORMAX) {
1223. 		impossible("DOORMAX exceeded?");
1224. 		return;
1225. 	}
1226. 
1227. 	dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
1228. }
1229. 
1230. boolean
1231. occupied(x, y)
1232. register xchar x, y;
1233. {
1234. 	return((boolean)(t_at(x, y)
1235. 		|| IS_FURNITURE(levl[x][y].typ)
1236. 		|| is_lava(x,y)
1237. 		|| is_pool(x,y)
1238. 		|| invocation_pos(x,y)
1239. 		));
1240. }
1241. 
1242. /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
1243. /* if tm != null, make trap at that location */
1244. void
1245. mktrap(num, mazeflag, croom, tm)
1246. register int num, mazeflag;
1247. register struct mkroom *croom;
1248. coord *tm;
1249. {
1250. 	register int kind;
1251. 	coord m;
1252. 
1253. 	/* no traps in pools */
1254. 	if (tm && is_pool(tm->x,tm->y)) return;
1255. 
1256. 	if (num > 0 && num < TRAPNUM) {
1257. 	    kind = num;
1258. #ifdef REINCARNATION
1259. 	} else if (Is_rogue_level(&u.uz)) {
1260. 	    switch (rn2(7)) {
1261. 		default: kind = BEAR_TRAP; break; /* 0 */
1262. 		case 1: kind = ARROW_TRAP; break;
1263. 		case 2: kind = DART_TRAP; break;
1264. 		case 3: kind = TRAPDOOR; break;
1265. 		case 4: kind = PIT; break;
1266. 		case 5: kind = SLP_GAS_TRAP; break;
1267. 		case 6: kind = RUST_TRAP; break;
1268. 	    }
1269. #endif
1270. 	} else if (Inhell && !rn2(5)) {
1271. 	    /* bias the frequency of fire traps in Gehennom */
1272. 	    kind = FIRE_TRAP;
1273. 	} else {
1274. 	    unsigned lvl = level_difficulty();
1275. 
1276. 	    do {
1277. 		kind = rnd(TRAPNUM-1);
1278. 		/* reject "too hard" traps */
1279. 		switch (kind) {
1280. 		    case MAGIC_PORTAL:
1281. 			kind = NO_TRAP; break;
1282. 		    case ROLLING_BOULDER_TRAP:
1283. 		    case SLP_GAS_TRAP:
1284. 			if (lvl < 2) kind = NO_TRAP; break;
1285. 		    case LEVEL_TELEP:
1286. 			if (lvl < 5 || level.flags.noteleport)
1287. 			    kind = NO_TRAP; break;
1288. 		    case SPIKED_PIT:
1289. 			if (lvl < 5) kind = NO_TRAP; break;
1290. 		    case LANDMINE:
1291. 			if (lvl < 6) kind = NO_TRAP; break;
1292. 		    case WEB:
1293. 			if (lvl < 7) kind = NO_TRAP; break;
1294. 		    case STATUE_TRAP:
1295. 		    case POLY_TRAP:
1296. 			if (lvl < 8) kind = NO_TRAP; break;
1297. 		    case FIRE_TRAP:
1298. 			if (!Inhell) kind = NO_TRAP; break;
1299. 		    case TELEP_TRAP:
1300. 			if (level.flags.noteleport) kind = NO_TRAP; break;
1301. 		    case HOLE:
1302. 			/* make these much less often than other traps */
1303. 			if (rn2(7)) kind = NO_TRAP; break;
1304. 		}
1305. 	    } while (kind == NO_TRAP);
1306. 	}
1307. 
1308. 	if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz))
1309. 		kind = ROCKTRAP;
1310. 
1311. 	if (tm)
1312. 	    m = *tm;
1313. 	else {
1314. 	    register int tryct = 0;
1315. 	    boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT ||
1316. 				     kind == TRAPDOOR || kind == HOLE);
1317. 
1318. 	    do {
1319. 		if (++tryct > 200)
1320. 		    return;
1321. 		if (mazeflag)
1322. 		    mazexy(&m);
1323. 		else if (!somexy(croom,&m))
1324. 		    return;
1325. 	    } while (occupied(m.x, m.y) ||
1326. 			(avoid_boulder && sobj_at(BOULDER, m.x, m.y)));
1327. 	}
1328. 
1329. 	(void) maketrap(m.x, m.y, kind);
1330. 	if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER],
1331. 						m.x, m.y, NO_MM_FLAGS);
1332. }
1333. 
1334. void
1335. mkstairs(x, y, up, croom)
1336. xchar x, y;
1337. char  up;
1338. struct mkroom *croom;
1339. {
1340. 	if (!x) {
1341. 	    impossible("mkstairs:  bogus stair attempt at <%d,%d>", x, y);
1342. 	    return;
1343. 	}
1344. 
1345. 	/*
1346. 	 * We can't make a regular stair off an end of the dungeon.  This
1347. 	 * attempt can happen when a special level is placed at an end and
1348. 	 * has an up or down stair specified in its description file.
1349. 	 */
1350. 	if ((dunlev(&u.uz) == 1 && up) ||
1351. 			(dunlev(&u.uz) == real_dunlevs_in_dungeon(&u.uz) && !up))
1352. 	    return;
1353. 
1354. 	if(up) {
1355. 		xupstair = x;
1356. 		yupstair = y;
1357. 		upstairs_room = croom;
1358. 	} else {
1359. 		xdnstair = x;
1360. 		ydnstair = y;
1361. 		dnstairs_room = croom;
1362. 	}
1363. 
1364. 	levl[x][y].typ = STAIRS;
1365. 	levl[x][y].ladder = up ? LA_UP : LA_DOWN;
1366. }
1367. 
1368. STATIC_OVL
1369. void
1370. mkfount(mazeflag,croom)
1371. register int mazeflag;
1372. register struct mkroom *croom;
1373. {
1374. 	coord m;
1375. 	register int tryct = 0;
1376. 
1377. 	do {
1378. 	    if(++tryct > 200) return;
1379. 	    if(mazeflag)
1380. 		mazexy(&m);
1381. 	    else
1382. 		if (!somexy(croom, &m))
1383. 		    return;
1384. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1385. 
1386. 	/* Put a fountain at m.x, m.y */
1387. 	levl[m.x][m.y].typ = FOUNTAIN;
1388. 	/* Is it a "blessed" fountain? (affects drinking from fountain) */
1389. 	if(!rn2(7)) levl[m.x][m.y].blessedftn = 1;
1390. 
1391. 	level.flags.nfountains++;
1392. }
1393. 
1394. #ifdef SINKS
1395. STATIC_OVL void
1396. mksink(croom)
1397. register struct mkroom *croom;
1398. {
1399. 	coord m;
1400. 	register int tryct = 0;
1401. 
1402. 	do {
1403. 	    if(++tryct > 200) return;
1404. 	    if (!somexy(croom, &m))
1405. 		return;
1406. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1407. 
1408. 	/* Put a sink at m.x, m.y */
1409. 	levl[m.x][m.y].typ = SINK;
1410. 
1411. 	level.flags.nsinks++;
1412. }
1413. 
1414. static void
1415. mktoilet(croom)
1416. register struct mkroom *croom;
1417. {
1418. 	coord m;
1419. 	register int tryct = 0;
1420. 
1421. 	do {
1422. 	    if(++tryct > 200) return;
1423. 	    if (!somexy(croom, &m))
1424. 		return;
1425. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1426. 
1427. 	/* Put a toilet at m.x, m.y */
1428. 	levl[m.x][m.y].typ = TOILET;
1429. 
1430. 	level.flags.nsinks++; /* counted as a sink for sounds.c */
1431. }
1432. #endif /* SINKS */
1433. 
1434. STATIC_OVL void
1435. mkaltar(croom)
1436. register struct mkroom *croom;
1437. {
1438. 	coord m;
1439. 	register int tryct = 0;
1440. 	aligntyp al;
1441. 
1442. 	if(croom->rtype != OROOM) return;
1443. 
1444. 	do {
1445. 	    if(++tryct > 200) return;
1446. 	    if (!somexy(croom, &m))
1447. 		return;
1448. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1449. 
1450. 	/* Put an altar at m.x, m.y */
1451. 	levl[m.x][m.y].typ = ALTAR;
1452. 
1453. 	/* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
1454. 	al = rn2((int)A_LAWFUL+2) - 1;
1455. 	levl[m.x][m.y].altarmask = Align2amask( al );
1456. }
1457. 
1458. static void
1459. mkgrave(croom)
1460. struct mkroom *croom;
1461. {
1462. 	coord m;
1463. 	register int tryct = 0;
1464. 	register struct obj *otmp;
1465. 	boolean dobell = !rn2(10);
1466. 
1467. 
1468. 	if(croom->rtype != OROOM) return;
1469. 
1470. 	do {
1471. 	    if(++tryct > 200) return;
1472. 	    if (!somexy(croom, &m))
1473. 		return;
1474. 	} while (occupied(m.x, m.y) || bydoor(m.x, m.y));
1475. 
1476. 	/* Put a grave at m.x, m.y */
1477. 	make_grave(m.x, m.y, dobell ? "Saved by the bell!" : (char *) 0);
1478. 
1479. 	/* Possibly fill it with objects */
1480. 	if (!rn2(3)) (void) mkgold(0L, m.x, m.y);
1481. 	for (tryct = rn2(5); tryct; tryct--) {
1482. 	    otmp = mkobj(RANDOM_CLASS, TRUE);
1483. 	    if (!otmp) return;
1484. 	    curse(otmp);
1485. 	    otmp->ox = m.x;
1486. 	    otmp->oy = m.y;
1487. 	    add_to_buried(otmp);
1488. 	}
1489. 
1490. 	/* Leave a bell, in case we accidentally buried someone alive */
1491. 	if (dobell) (void) mksobj_at(BELL, m.x, m.y, TRUE, FALSE);
1492. 	return;
1493. }
1494. 
1495. /* maze levels have slightly different constraints from normal levels */
1496. #define x_maze_min 2
1497. #define y_maze_min 2
1498. /*
1499.  * Major level transmutation: add a set of stairs (to the Sanctum) after
1500.  * an earthquake that leaves behind a a new topology, centered at inv_pos.
1501.  * Assumes there are no rooms within the invocation area and that inv_pos
1502.  * is not too close to the edge of the map.  Also assume the hero can see,
1503.  * which is guaranteed for normal play due to the fact that sight is needed
1504.  * to read the Book of the Dead.
1505.  */
1506. void
1507. mkinvokearea()
1508. {
1509.     int dist;
1510.     xchar xmin = inv_pos.x, xmax = inv_pos.x;
1511.     xchar ymin = inv_pos.y, ymax = inv_pos.y;
1512.     register xchar i;
1513. 
1514.     pline_The("floor shakes violently under you!");
1515.     pline_The("walls around you begin to bend and crumble!");
1516.     display_nhwindow(WIN_MESSAGE, TRUE);
1517. 
1518.     mkinvpos(xmin, ymin, 0);		/* middle, before placing stairs */
1519. 
1520.     for(dist = 1; dist < 7; dist++) {
1521. 	xmin--; xmax++;
1522. 
1523. 	/* top and bottom */
1524. 	if(dist != 3) { /* the area is wider that it is high */
1525. 	    ymin--; ymax++;
1526. 	    for(i = xmin+1; i < xmax; i++) {
1527. 		mkinvpos(i, ymin, dist);
1528. 		mkinvpos(i, ymax, dist);
1529. 	    }
1530. 	}
1531. 
1532. 	/* left and right */
1533. 	for(i = ymin; i <= ymax; i++) {
1534. 	    mkinvpos(xmin, i, dist);
1535. 	    mkinvpos(xmax, i, dist);
1536. 	}
1537. 
1538. 	flush_screen(1);	/* make sure the new glyphs shows up */
1539. 	delay_output();
1540.     }
1541. 
1542.     You("are standing at the top of a stairwell leading down!");
1543.     mkstairs(u.ux, u.uy, 0, (struct mkroom *)0); /* down */
1544.     newsym(u.ux, u.uy);
1545.     vision_full_recalc = 1;	/* everything changed */
1546. }
1547. 
1548. /* Change level topology.  Boulders in the vicinity are eliminated.
1549.  * Temporarily overrides vision in the name of a nice effect.
1550.  */
1551. STATIC_OVL void
1552. mkinvpos(x,y,dist)
1553. xchar x,y;
1554. int dist;
1555. {
1556.     struct trap *ttmp;
1557.     struct obj *otmp;
1558.     boolean make_rocks;
1559.     register struct rm *lev = &levl[x][y];
1560. 
1561.     /* clip at existing map borders if necessary */
1562.     if (!within_bounded_area(x, y, x_maze_min + 1, y_maze_min + 1,
1563. 				   x_maze_max - 1, y_maze_max - 1)) {
1564. 	/* only outermost 2 columns and/or rows may be truncated due to edge */
1565. 	if (dist < (7 - 2))
1566. 	    panic("mkinvpos: <%d,%d> (%d) off map edge!", x, y, dist);
1567. 	return;
1568.     }
1569. 
1570.     /* clear traps */
1571.     if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
1572. 
1573.     /* clear boulders; leave some rocks for non-{moat|trap} locations */
1574.     make_rocks = (dist != 1 && dist != 4 && dist != 5) ? TRUE : FALSE;
1575.     while ((otmp = sobj_at(BOULDER, x, y)) != 0) {
1576. 	if (make_rocks) {
1577. 	    fracture_rock(otmp);
1578. 	    make_rocks = FALSE;		/* don't bother with more rocks */
1579. 	} else {
1580. 	    obj_extract_self(otmp);
1581. 	    obfree(otmp, (struct obj *)0);
1582. 	}
1583.     }
1584.     unblock_point(x,y);	/* make sure vision knows this location is open */
1585. 
1586.     /* fake out saved state */
1587.     lev->seenv = 0;
1588.     lev->doormask = 0;
1589.     if(dist < 6) lev->lit = TRUE;
1590.     lev->waslit = TRUE;
1591.     lev->horizontal = FALSE;
1592.     viz_array[y][x] = (dist < 6 ) ?
1593. 	(IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */
1594. 	COULD_SEE;
1595. 
1596.     switch(dist) {
1597.     case 1: /* fire traps */
1598. 	if (is_pool(x,y)) break;
1599. 	lev->typ = ROOM;
1600. 	ttmp = maketrap(x, y, FIRE_TRAP);
1601. 	if (ttmp) ttmp->tseen = TRUE;
1602. 	break;
1603.     case 0: /* lit room locations */
1604.     case 2:
1605.     case 3:
1606.     case 6: /* unlit room locations */
1607. 	lev->typ = ROOM;
1608. 	break;
1609.     case 4: /* pools (aka a wide moat) */
1610.     case 5:
1611. 	lev->typ = MOAT;
1612. 	/* No kelp! */
1613. 	break;
1614.     default:
1615. 	impossible("mkinvpos called with dist %d", dist);
1616. 	break;
1617.     }
1618. 
1619.     /* display new value of position; could have a monster/object on it */
1620.     newsym(x,y);
1621. }
1622. 
1623. /*
1624.  * The portal to Ludios is special.  The entrance can only occur within a
1625.  * vault in the main dungeon at a depth greater than 10.  The Ludios branch
1626.  * structure reflects this by having a bogus "source" dungeon:  the value
1627.  * of n_dgns (thus, Is_branchlev() will never find it).
1628.  *
1629.  * Ludios will remain isolated until the branch is corrected by this function.
1630.  */
1631. STATIC_OVL void
1632. mk_knox_portal(x, y)
1633. xchar x, y;
1634. {
1635. 	extern int n_dgns;		/* from dungeon.c */
1636. 	d_level *source;
1637. 	branch *br;
1638. 	schar u_depth;
1639. 
1640. 	br = dungeon_branch("Fort Ludios");
1641. 	if (on_level(&knox_level, &br->end1)) {
1642. 	    source = &br->end2;
1643. 	} else {
1644. 	    /* disallow Knox branch on a level with one branch already */
1645. 	    if(Is_branchlev(&u.uz))
1646. 		return;
1647. 	    source = &br->end1;
1648. 	}
1649. 
1650. 	/* Already set or 2/3 chance of deferring until a later level. */
1651. 	if (source->dnum < n_dgns || (rn2(3)
1652. #ifdef WIZARD
1653. 				      && !wizard
1654. #endif
1655. 				      )) return;
1656. 
1657. 	if (! (u.uz.dnum == oracle_level.dnum	    /* in main dungeon */
1658. 		&& !at_dgn_entrance("The Quest")    /* but not Quest's entry */
1659. 		&& (u_depth = depth(&u.uz)) > 10    /* beneath 10 */
1660. 		&& u_depth < depth(&medusa_level))) /* and above Medusa */
1661. 	    return;
1662. 
1663. 	/* Adjust source to be current level and re-insert branch. */
1664. 	*source = u.uz;
1665. 	insert_branch(br, TRUE);
1666. 
1667. #ifdef DEBUG
1668. 	pline("Made knox portal.");
1669. #endif
1670. 	place_branch(br, x, y);
1671. }
1672. 
1673. /*mklev.c*/