Source:NetHack 3.1.0/mklev.c

From NetHackWiki
Revision as of 06:45, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.1.0/mklev.c moved to Source:NetHack 3.1.0/mklev.c: Robot: moved page)
(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 NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/mklev.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: @(#)mklev.c	3.1	92/10/10	*/
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 void FDECL(mkfount,(int,struct mkroom *));
22.   #ifdef SINKS
23.   static void FDECL(mksink,(struct mkroom *));
24.   #endif
25.   static void FDECL(mkaltar,(struct mkroom *));
26.   static void NDECL(makevtele);
27.   static void NDECL(clear_level_structures);
28.   static void NDECL(makelevel);
29.   static boolean FDECL(bydoor,(XCHAR_P,XCHAR_P));
30.   static struct mkroom *FDECL(find_branch_room, (coord *));
31.   static struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
32.   static boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*));
33.   static void FDECL(makeniche,(int));
34.   static void NDECL(make_niches);
35.   STATIC_PTR int FDECL(do_comp,(const genericptr,const genericptr));
36.   static void FDECL(dosdoor,(XCHAR_P,XCHAR_P,struct mkroom *,int));
37.   static void FDECL(join,(int,int,BOOLEAN_P));
38.   static void FDECL(do_room_or_subroom, (struct mkroom *,int,int,int,int,
39.   				       BOOLEAN_P,SCHAR_P,BOOLEAN_P,BOOLEAN_P));
40.   static void NDECL(makerooms);
41.   static void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
42.   static void FDECL(mkinvpos, (XCHAR_P,XCHAR_P,int));
43.   #ifdef MULDGN
44.   static void FDECL(mk_knox_portal, (XCHAR_P,XCHAR_P));
45.   #endif
46.   
47.   #define create_vault()	create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
48.   #define init_vault()	vault_x = -1
49.   #define do_vault()	(vault_x != -1)
50.   static xchar		vault_x, vault_y;
51.   boolean goldseen;
52.   static boolean made_branch;	/* used only during level creation */
53.   
54.   /* Args must be (const genericptr) so that qsort will always be happy. */
55.   
56.   STATIC_PTR int
57.   do_comp(vx,vy)
58.   const genericptr vx;
59.   const genericptr vy;
60.   {
61.   #ifdef LINT
62.   /* lint complains about possible pointer alignment problems, but we know
63.      that vx and vy are always properly aligned. Hence, the following
64.      bogus definition:
65.   */
66.   	return (vx == vy) ? 0 : -1;
67.   #else
68.   	register const struct mkroom *x, *y;
69.   
70.   	x = (const struct mkroom *)vx;
71.   	y = (const struct mkroom *)vy;
72.   	if(x->lx < y->lx) return(-1);
73.   	return(x->lx > y->lx);
74.   #endif /* LINT */
75.   }
76.   
77.   static void
78.   finddpos(cc, xl,yl,xh,yh)
79.   coord	*cc;
80.   xchar	xl,yl,xh,yh;
81.   {
82.   	register xchar x, y;
83.   
84.   	x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
85.   	y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
86.   	if(okdoor(x, y))
87.   		goto gotit;
88.   
89.   	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
90.   		if(okdoor(x, y))
91.   			goto gotit;
92.   
93.   	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
94.   		if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
95.   			goto gotit;
96.   	/* cannot find something reasonable -- strange */
97.   	x = xl;
98.   	y = yh;
99.   gotit:
100.  	cc->x = x;
101.  	cc->y = y;
102.  	return;
103.  }
104.  
105.  void
106.  sort_rooms()
107.  {
108.  #if defined(SYSV) || defined(DGUX)
109.  	qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), do_comp);
110.  #else
111.  	qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), do_comp);
112.  #endif
113.  }
114.  
115.  static void
116.  do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
117.      register struct mkroom *croom;
118.      int lowx, lowy;
119.      register int hix, hiy;
120.      boolean lit;
121.      schar rtype;
122.      boolean special;
123.      boolean is_room;
124.  {
125.  	register int x, y;
126.  	struct rm *lev;
127.  
128.  	/* locations might bump level edges in wall-less rooms */
129.  	/* add/subtract 1 to allow for edge locations */
130.  	if(!lowx) lowx++;
131.  	if(!lowy) lowy++;
132.  	if(hix >= COLNO-1) hix = COLNO-2;
133.  	if(hiy >= ROWNO-1) hiy = ROWNO-2;
134.  
135.  	if(lit) {
136.  		for(x = lowx-1; x <= hix+1; x++) {
137.  			lev = &levl[x][max(lowy-1,0)];
138.  			for(y = lowy-1; y <= hiy+1; y++)
139.  				lev++->lit = 1;
140.  		}
141.  		croom->rlit = 1;
142.  	} else
143.  		croom->rlit = 0;
144.  
145.  	croom->lx = lowx;
146.  	croom->hx = hix;
147.  	croom->ly = lowy;
148.  	croom->hy = hiy;
149.  	croom->rtype = rtype;
150.  	croom->doorct = 0;
151.  	/* if we're not making a vault, doorindex will still be 0
152.  	 * if we are, we'll have problems adding niches to the previous room
153.  	 * unless fdoor is at least doorindex
154.  	 */
155.  	croom->fdoor = doorindex;
156.  	croom->irregular = FALSE;
157.  
158.  	croom->nsubrooms = 0;
159.  	croom->sbrooms[0] = (struct mkroom *) 0;
160.  	if (!special) {
161.  	    for(x = lowx-1; x <= hix+1; x++)
162.  		for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
163.  		    levl[x][y].typ = HWALL;
164.  		    levl[x][y].horizontal = 1;	/* For open/secret doors. */
165.  		}
166.  	    for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
167.  		for(y = lowy; y <= hiy; y++) {
168.  		    levl[x][y].typ = VWALL;
169.  		    levl[x][y].horizontal = 0;	/* For open/secret doors. */
170.  		}
171.  	    for(x = lowx; x <= hix; x++) {
172.  		lev = &levl[x][lowy];
173.  		for(y = lowy; y <= hiy; y++)
174.  		    lev++->typ = ROOM;
175.  	    }
176.  	    if (is_room) {
177.  		levl[lowx-1][lowy-1].typ = TLCORNER;
178.  		levl[hix+1][lowy-1].typ = TRCORNER;
179.  		levl[lowx-1][hiy+1].typ = BLCORNER;
180.  		levl[hix+1][hiy+1].typ = BRCORNER;
181.  	    } else {	/* a subroom */
182.  		wallification(lowx-1, lowy-1, hix+1, hiy+1);
183.  	    }
184.  	}
185.  }
186.  
187.  
188.  void
189.  add_room(lowx, lowy, hix, hiy, lit, rtype, special)
190.  register int lowx, lowy, hix, hiy;
191.  boolean lit;
192.  schar rtype;
193.  boolean special;
194.  {
195.  	register struct mkroom *croom;
196.  
197.  	croom = &rooms[nroom];
198.  	do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
199.  					    rtype, special, (boolean) TRUE);
200.  	croom++;
201.  	croom->hx = -1;
202.  	nroom++;
203.  }
204.  
205.  void
206.  add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
207.  struct mkroom *proom;
208.  register int lowx, lowy, hix, hiy;
209.  boolean lit;
210.  schar rtype;
211.  boolean special;
212.  {
213.  	register struct mkroom *croom;
214.  
215.  	croom = &subrooms[nsubroom];
216.  	do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit,
217.  					    rtype, special, (boolean) FALSE);
218.  	proom->sbrooms[proom->nsubrooms++] = croom;
219.  	croom++;
220.  	croom->hx = -1;
221.  	nsubroom++;
222.  }
223.  
224.  static void
225.  makerooms()
226.  {
227.  	boolean tried_vault = FALSE;
228.  
229.  	/* make rooms until satisfied */
230.  	/* rnd_rect() will returns 0 if no more rects are available... */
231.  	while(nroom < MAXNROFROOMS && rnd_rect()) {
232.  		if(nroom >= (MAXNROFROOMS/6) && rn2(2) && !tried_vault) {
233.  			tried_vault = TRUE;
234.  			if (create_vault()) {
235.  				vault_x = rooms[nroom].lx;
236.  				vault_y = rooms[nroom].ly;
237.  				rooms[nroom].hx = -1;
238.  			}
239.  		} else
240.  		    if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
241.  			return;
242.  	}
243.  	return;
244.  }
245.  
246.  static void
247.  join(a,b,nxcor)
248.  register int a, b;
249.  boolean nxcor;
250.  {
251.  	coord cc,tt, org, dest;
252.  	register int tx, ty, xx, yy;
253.  	register struct mkroom *croom, *troom;
254.  	register int dx, dy;
255.  
256.  	croom = &rooms[a];
257.  	troom = &rooms[b];
258.  
259.  	/* find positions cc and tt for doors in croom and troom
260.  	   and direction for a corridor between them */
261.  
262.  	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
263.  	if(troom->lx > croom->hx) {
264.  		dx = 1;
265.  		dy = 0;
266.  		xx = croom->hx+1;
267.  		tx = troom->lx-1;
268.  		finddpos(&cc, xx, croom->ly, xx, croom->hy);
269.  		finddpos(&tt, tx, troom->ly, tx, troom->hy);
270.  	} else if(troom->hy < croom->ly) {
271.  		dy = -1;
272.  		dx = 0;
273.  		yy = croom->ly-1;
274.  		finddpos(&cc, croom->lx, yy, croom->hx, yy);
275.  		ty = troom->hy+1;
276.  		finddpos(&tt, troom->lx, ty, troom->hx, ty);
277.  	} else if(troom->hx < croom->lx) {
278.  		dx = -1;
279.  		dy = 0;
280.  		xx = croom->lx-1;
281.  		tx = troom->hx+1;
282.  		finddpos(&cc, xx, croom->ly, xx, croom->hy);
283.  		finddpos(&tt, tx, troom->ly, tx, troom->hy);
284.  	} else {
285.  		dy = 1;
286.  		dx = 0;
287.  		yy = croom->hy+1;
288.  		ty = troom->ly-1;
289.  		finddpos(&cc, croom->lx, yy, croom->hx, yy);
290.  		finddpos(&tt, troom->lx, ty, troom->hx, ty);
291.  	}
292.  	xx = cc.x;
293.  	yy = cc.y;
294.  	tx = tt.x - dx;
295.  	ty = tt.y - dy;
296.  	if(nxcor && levl[xx+dx][yy+dy].typ)
297.  		return;
298.  	if (okdoor(xx,yy) || !nxcor)
299.  	    dodoor(xx,yy,croom);
300.  
301.  	org.x  = xx+dx; org.y  = yy+dy;
302.  	dest.x = tx; dest.y = ty;
303.  
304.  	if (!dig_corridor(org, dest, nxcor, CORR, STONE))
305.  	    return;
306.  
307.  	/* we succeeded in digging the corridor */
308.  	if (okdoor(tt.x, tt.y) || !nxcor)
309.  	    dodoor(tt.x, tt.y, troom);
310.  
311.  	if(smeq[a] < smeq[b])
312.  		smeq[b] = smeq[a];
313.  	else
314.  		smeq[a] = smeq[b];
315.  }
316.  
317.  void
318.  makecorridors()
319.  {
320.  	int a, b, i;
321.  	boolean any = TRUE;
322.  
323.  	for(a = 0; a < nroom-1; a++) {
324.  		join(a, a+1, FALSE);
325.  		if(!rn2(50)) break; /* allow some randomness */
326.  	}
327.  	for(a = 0; a < nroom-2; a++)
328.  	    if(smeq[a] != smeq[a+2])
329.  		join(a, a+2, FALSE);
330.  	for(a = 0; any && a < nroom; a++) {
331.  	    any = FALSE;
332.  	    for(b = 0; b < nroom; b++)
333.  		if(smeq[a] != smeq[b]) {
334.  		    join(a, b, FALSE);
335.  		    any = TRUE;
336.  		}
337.  	}
338.  	if(nroom > 2)
339.  	    for(i = rn2(nroom) + 4; i; i--) {
340.  		a = rn2(nroom);
341.  		b = rn2(nroom-2);
342.  		if(b >= a) b += 2;
343.  		join(a, b, TRUE);
344.  	    }
345.  }
346.  
347.  void
348.  add_door(x,y,aroom)
349.  register int x, y;
350.  register struct mkroom *aroom;
351.  {
352.  	register struct mkroom *broom;
353.  	register int tmp;
354.  
355.  	aroom->doorct++;
356.  	broom = aroom+1;
357.  	if(broom->hx < 0)
358.  		tmp = doorindex;
359.  	else
360.  		for(tmp = doorindex; tmp > broom->fdoor; tmp--)
361.  			doors[tmp] = doors[tmp-1];
362.  	doorindex++;
363.  	doors[tmp].x = x;
364.  	doors[tmp].y = y;
365.  	for( ; broom->hx >= 0; broom++) broom->fdoor++;
366.  }
367.  
368.  static void
369.  dosdoor(x,y,aroom,type)
370.  register xchar x, y;
371.  register struct mkroom *aroom;
372.  register int type;
373.  {
374.  	boolean shdoor = ((*in_rooms(x, y, SHOPBASE))? TRUE : FALSE);
375.  
376.  	if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
377.  		type = DOOR;
378.  	levl[x][y].typ = type;
379.  	if(type == DOOR) {
380.  	    if(!rn2(3)) {      /* is it a locked door, closed, or a doorway? */
381.  		if(!rn2(5))
382.  		    levl[x][y].doormask = D_ISOPEN;
383.  		else if(!rn2(6))
384.  		    levl[x][y].doormask = D_LOCKED;
385.  		else
386.  		    levl[x][y].doormask = D_CLOSED;
387.  
388.  		if (levl[x][y].doormask != D_ISOPEN && !shdoor && !rn2(25))
389.  		    levl[x][y].doormask |= D_TRAPPED;
390.  	    } else
391.  #ifdef STUPID
392.  		if (shdoor)
393.  			levl[x][y].doormask = D_ISOPEN;
394.  		else
395.  			levl[x][y].doormask = D_NODOOR;
396.  #else
397.  		levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
398.  #endif
399.  	    if(levl[x][y].doormask & D_TRAPPED) {
400.  		struct monst *mtmp;
401.  
402.  		if (level_difficulty() >= 9 && !rn2(5) &&
403.  		   !((mons[PM_SMALL_MIMIC].geno & (G_GENOD | G_EXTINCT)) &&
404.  		     (mons[PM_LARGE_MIMIC].geno & (G_GENOD | G_EXTINCT)) &&
405.  		     (mons[PM_GIANT_MIMIC].geno & (G_GENOD | G_EXTINCT)))) {
406.  		    /* make a mimic instead */
407.  		    levl[x][y].doormask = D_NODOOR;
408.  		    mtmp = makemon(mkclass(S_MIMIC,0), x, y);
409.  		    if (mtmp)
410.  			set_mimic_sym(mtmp);
411.  		}
412.  	    }
413.  	    /* newsym(x,y); */
414.  	} else { /* SDOOR */
415.  		if(shdoor || !rn2(5))	levl[x][y].doormask = D_LOCKED;
416.  		else			levl[x][y].doormask = D_CLOSED;
417.  
418.  		if(!shdoor && !rn2(20)) levl[x][y].doormask |= D_TRAPPED;
419.  	}
420.  
421.  	add_door(x,y,aroom);
422.  }
423.  
424.  static boolean
425.  place_niche(aroom,dy,xx,yy)
426.  register struct mkroom *aroom;
427.  int *dy, *xx, *yy;
428.  {
429.  	coord dd;
430.  
431.  	if(rn2(2)) {
432.  	    *dy = 1;
433.  	    finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1);
434.  	} else {
435.  	    *dy = -1;
436.  	    finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1);
437.  	}
438.  	*xx = dd.x;
439.  	*yy = dd.y;
440.  	return(isok(*xx,*yy+*dy) && levl[*xx][(*yy)+(*dy)].typ == STONE);
441.  }
442.  
443.  /* there should be one of these per trap */
444.  const char *trap_engravings[TRAPNUM] = {
445.  				"", "", "", "", "", "", "",
446.  				"", "", "", "", "", "",
447.  				"ad ae?ar um", "?la? ?as ?er?", "ad ae?ar um",
448.  				"", "", "", ""
449.  #ifdef POLYSELF
450.  				,""
451.  #endif
452.  				};
453.  
454.  static void
455.  makeniche(trap_type)
456.  int trap_type;
457.  {
458.  	register struct mkroom *aroom;
459.  	register struct rm *rm;
460.  	register int vct = 8;
461.  	int dy, xx, yy;
462.  	register struct trap *ttmp;
463.  
464.  	if(doorindex < DOORMAX)
465.  	  while(vct--) {
466.  	    aroom = &rooms[rn2(nroom)];
467.  	    if(aroom->rtype != OROOM) continue;	/* not an ordinary room */
468.  	    if(aroom->doorct == 1 && rn2(5)) continue;
469.  	    if(!place_niche(aroom,&dy,&xx,&yy)) continue;
470.  
471.  	    rm = &levl[xx][yy+dy];
472.  	    if(trap_type || !rn2(4)) {
473.  
474.  		rm->typ = SCORR;
475.  		if(trap_type) {
476.  		    if(trap_type == TRAPDOOR && !Can_fall_thru(&u.uz))
477.  			trap_type = ROCKTRAP;
478.  		    ttmp = maketrap(xx, yy+dy, trap_type);
479.  		    ttmp->once = 1;
480.  		    if (*trap_engravings[trap_type])
481.  			make_engr_at(xx, yy-dy, trap_engravings[trap_type], 0L, DUST);
482.  		}
483.  		dosdoor(xx, yy, aroom, SDOOR);
484.  	    } else {
485.  		rm->typ = CORR;
486.  		if(rn2(7))
487.  		    dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
488.  		else {
489.  		    (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy, TRUE);
490.  		    if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE);
491.  		}
492.  	    }
493.  	    return;
494.  	}
495.  }
496.  
497.  static void
498.  make_niches()
499.  {
500.  	register int ct = rnd((nroom>>1) + 1);
501.  	boolean	ltptr = TRUE,
502.  		vamp = TRUE;
503.  
504.  	while(ct--) {
505.  
506.  		if(depth(&u.uz) > 15 && !rn2(6) && ltptr) {
507.  			ltptr = FALSE;
508.  			makeniche(LEVEL_TELEP);
509.  		} else if(depth(&u.uz) > 5 && depth(&u.uz) < 25
510.  							&& !rn2(6) && vamp) {
511.  			vamp = FALSE;
512.  			makeniche(TRAPDOOR);
513.  		} else	makeniche(NO_TRAP);
514.  	}
515.  }
516.  
517.  static void
518.  makevtele()
519.  {
520.  	makeniche(TELEP_TRAP);
521.  }
522.  
523.  /* clear out various globals that keep information on the current level.
524.   * some of this is only necessary for some types of levels (maze, normal,
525.   * special) but it's easier to put it all in one place than make sure
526.   * each type initializes what it needs to separately.
527.   */
528.  static void
529.  clear_level_structures()
530.  {
531.  	static struct rm zerorm = { cmap_to_glyph(S_stone),
532.  						0, 0, 0, 0, 0, 0, 0, 0 };
533.  	register int x,y;
534.  	register struct rm *lev;
535.  
536.  	for(x=0; x<COLNO; x++) {
537.  	    lev = &levl[x][0];
538.  	    for(y=0; y<ROWNO; y++) {
539.  		*lev++ = zerorm;
540.  #ifdef MICROPORT_BUG
541.  		level.objects[x][y] = (struct obj *)0;
542.  		level.monsters[x][y] = (struct monst *)0;
543.  #endif
544.  	    }
545.  	}
546.  #ifndef MICROPORT_BUG
547.  	(void) memset((genericptr_t)level.objects, 0, sizeof(level.objects));
548.  	(void) memset((genericptr_t)level.monsters, 0, sizeof(level.monsters));
549.  #endif
550.  	level.flags.nfountains = 0;
551.  	level.flags.nsinks = 0;
552.  	level.flags.has_shop = 0;
553.  	level.flags.has_vault = 0;
554.  	level.flags.has_zoo = 0;
555.  	level.flags.has_court = 0;
556.  	level.flags.has_morgue = 0;
557.  	level.flags.has_beehive = 0;
558.  #ifdef ARMY
559.  	level.flags.has_barracks = 0;
560.  #endif
561.  	level.flags.has_temple = 0;
562.  	level.flags.has_swamp = 0;
563.  	level.flags.noteleport = 0;
564.  	level.flags.hardfloor = 0;
565.  	level.flags.nommap = 0;
566.  	level.flags.hero_memory = 1;
567.  	level.flags.shortsighted = 0;
568.  	level.flags.is_maze_lev = 0;
569.  	level.flags.is_cavernous_lev = 0;
570.  
571.  	nroom = 0;
572.  	rooms[0].hx = -1;
573.  	nsubroom = 0;
574.  	doorindex = 0;
575.  	init_rect();
576.  	init_vault();
577.  	xdnstair = ydnstair = xupstair = yupstair = 0;
578.  	sstairs.sx = sstairs.sy = 0;
579.  	xdnladder = ydnladder = xupladder = yupladder = 0;
580.  	made_branch = FALSE;
581.  }
582.  
583.  static void
584.  makelevel()
585.  {
586.  	register struct mkroom *croom, *troom;
587.  	register int tryct;
588.  	register int x, y;
589.  	struct monst *tmonst;	/* always put a web with a spider */
590.  
591.  	if(wiz1_level.dlevel == 0) init_dungeons();
592.  	oinit();	/* assign level dependent obj probabilities */
593.  	clear_level_structures();
594.  
595.  	{
596.  	    register s_level *slev = Is_special(&u.uz);
597.  
598.  	    /* check for special levels */
599.  #ifdef REINCARNATION
600.  	    if (slev && !Is_rogue_level(&u.uz))
601.  #else
602.  	    if (slev)
603.  #endif
604.  	    {
605.  		    makemaz(slev->proto);
606.  		    return;
607.  	    } else if (dungeons[u.uz.dnum].proto[0]) {
608.  		    makemaz("");
609.  		    return;
610.  #ifdef MULDGN
611.  	    } else if (In_mines(&u.uz)) {
612.  		    makemaz("minefill");
613.  		    return;
614.  	    } else if (In_quest(&u.uz)) {
615.  		    char	fillname[9];
616.  		    s_level	*loc_lev;
617.  
618.  		    Sprintf(fillname, "%c-locate", pl_character[0]);
619.  		    loc_lev = find_level(fillname);
620.  
621.  		    Sprintf(fillname, "%c-fill", pl_character[0]);
622.  		    Strcat(fillname,
623.  			   (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
624.  		    makemaz(fillname);
625.  		    return;
626.  #endif
627.  	    } else if(In_hell(&u.uz) ||
628.  		  (rn2(5) && u.uz.dnum == medusa_level.dnum
629.  			  && depth(&u.uz) > depth(&medusa_level))) {
630.  		    makemaz("");
631.  		    return;
632.  	    }
633.  	}
634.  
635.  	/* otherwise, fall through - it's a "regular" level. */
636.  
637.  #ifdef REINCARNATION
638.  	if (Is_rogue_level(&u.uz)) {
639.  		makeroguerooms();
640.  		makerogueghost();
641.  	} else
642.  #endif
643.  		makerooms();
644.  	sort_rooms();
645.  
646.  	/* construct stairs (up and down in different rooms if possible) */
647.  	croom = &rooms[rn2(nroom)];
648.  	if (!Is_botlevel(&u.uz))
649.  	     mkstairs(somex(croom), somey(croom), 0, croom);	/* down */
650.  	if (nroom > 1) {
651.  	    troom = croom;
652.  	    croom = &rooms[rn2(nroom-1)];
653.  	    if (croom == troom) croom++;
654.  	}
655.  
656.  	if (u.uz.dlevel != 1) {
657.  	    xchar sx, sy;
658.  	    do {
659.  		sx = somex(croom);
660.  		sy = somey(croom);
661.  	    } while(occupied(sx, sy));
662.  	    mkstairs(sx, sy, 1, croom);	/* up */
663.  	}
664.  
665.  #ifdef REINCARNATION
666.  	if (Is_rogue_level(&u.uz)) goto skip0;
667.  #endif
668.  	makecorridors();
669.  	make_niches();
670.  
671.  	/* make a secret treasure vault, not connected to the rest */
672.  	if(do_vault()) {
673.  		xchar w,h;
674.  #ifdef DEBUG
675.  		debugpline("trying to make a vault...");
676.  #endif
677.  		w = 1;
678.  		h = 1;
679.  		if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
680.  		    fill_vault:
681.  			add_room(vault_x, vault_y, vault_x+w,
682.  				 vault_y+h, TRUE, VAULT, FALSE);
683.  			level.flags.has_vault = 1;
684.  			fill_room(&rooms[nroom - 1], FALSE);
685.  #ifdef MULDGN
686.  			mk_knox_portal(vault_x+w, vault_y+h);
687.  #endif
688.  			if(!rn2(3)) makevtele();
689.  		} else if(rnd_rect() && create_vault()) {
690.  			vault_x = rooms[nroom].lx;
691.  			vault_y = rooms[nroom].ly;
692.  			if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
693.  				goto fill_vault;
694.  			else
695.  				rooms[nroom].hx = -1;
696.  		}
697.  	}
698.  
699.  #ifdef WIZARD
700.  	if(wizard && getenv("SHOPTYPE")) mkroom(SHOPBASE); else
701.  #endif
702.  	if(depth(&u.uz) > 1 &&
703.  	   depth(&u.uz) < depth(&medusa_level) &&
704.  	   rn2(depth(&u.uz)) < 3) mkroom(SHOPBASE);
705.  	else if(depth(&u.uz) > 4 && !rn2(6)) mkroom(COURT);
706.  	else if(depth(&u.uz) > 6 && !rn2(7)) mkroom(ZOO);
707.  	else if(depth(&u.uz) > 8 && !rn2(5)) mkroom(TEMPLE);
708.  	else if(depth(&u.uz) > 9 && !rn2(5) &&
709.  	   !(mons[PM_KILLER_BEE].geno & (G_GENOD | G_EXTINCT))) mkroom(BEEHIVE);
710.  	else if(depth(&u.uz) > 11 && !rn2(6)) mkroom(MORGUE);
711.  	else
712.  #ifdef ARMY
713.  	if(depth(&u.uz) > 14 && !rn2(4) &&
714.  	   !(mons[PM_SOLDIER].geno & (G_GENOD | G_EXTINCT))) mkroom(BARRACKS);
715.  	else
716.  #endif
717.  	if(depth(&u.uz) > 18 && !rn2(6)) mkroom(SWAMP);
718.  
719.  #ifdef REINCARNATION
720.  skip0:
721.  #endif
722.  	/* Place multi-dungeon branch. */
723.  	place_branch(Is_branchlev(&u.uz), 0, 0);
724.  
725.  	/* for each room: put things inside */
726.  	for(croom = rooms; croom->hx > 0; croom++) {
727.  		if(croom->rtype != OROOM) continue;
728.  
729.  		/* put a sleeping monster inside */
730.  		/* Note: monster may be on the stairs. This cannot be
731.  		   avoided: maybe the player fell through a trap door
732.  		   while a monster was on the stairs. Conclusion:
733.  		   we have to check for monsters on the stairs anyway. */
734.  
735.  		if(u.uhave.amulet || !rn2(3)) {
736.  		    x = somex(croom); y = somey(croom);
737.  		    tmonst = makemon((struct permonst *) 0, x,y);
738.  		    if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER] &&
739.  			!is_pool(x,y))
740.  			(void) maketrap (x,y,WEB);
741.  		}
742.  		/* put traps and mimics inside */
743.  		goldseen = FALSE;
744.  		x = 8 - (level_difficulty()/6);
745.  		if (x <= 1) x = 2;
746.  		while (!rn2(x))
747.  		    mktrap(0,0,croom,(coord*)0);
748.  		if(!goldseen && !rn2(3)) mkgold(0L, somex(croom), somey(croom));
749.  #ifdef REINCARNATION
750.  		if(Is_rogue_level(&u.uz)) goto skip_nonrogue;
751.  #endif
752.  		if(!rn2(10)) mkfount(0,croom);
753.  #ifdef SINKS
754.  		if(!rn2(60)) mksink(croom);
755.  #endif
756.  		if(!rn2(60)) mkaltar(croom);
757.  		/* put statues inside */
758.  		if(!rn2(20))
759.  		    (void) mkcorpstat(STATUE, (struct permonst *)0,
760.  				      somex(croom), somey(croom), TRUE);
761.  
762.  		/* put box/chest inside;
763.  		 *  40% chance for at least 1 box, regardless of number
764.  		 *  of rooms; about 5 - 7.5% for 2 boxes, least likely
765.  		 *  when few rooms; chance for 3 or more is neglible.
766.  		 */
767.  		if(!rn2(nroom * 5 / 2))
768.  		    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
769.  				     somex(croom), somey(croom), TRUE);
770.  
771.  		/* maybe make some graffiti */
772.  		if(!rn2(27 + 3 * depth(&u.uz))) {
773.  		    const char *mesg = random_engraving();
774.  		    if (mesg) {
775.  			do {
776.  			    x = somex(croom);  y = somey(croom);
777.  			} while(levl[x][y].typ != ROOM && !rn2(40));
778.  			if (!(IS_POOL(levl[x][y].typ) ||
779.  			      IS_FURNITURE(levl[x][y].typ)))
780.  			    make_engr_at(x, y, mesg, 0L, MARK);
781.  		    }
782.  		}
783.  
784.  #ifdef REINCARNATION
785.  	skip_nonrogue:
786.  #endif
787.  		if(!rn2(3)) {
788.  		    (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
789.  		    tryct = 0;
790.  		    while(!rn2(5)) {
791.  			if(++tryct > 100) {
792.  			    impossible("tryct overflow4");
793.  			    break;
794.  			}
795.  			(void) mkobj_at(0, somex(croom), somey(croom), TRUE);
796.  		    }
797.  		}
798.  	}
799.  }
800.  
801.  void
802.  mklev()
803.  {
804.  	struct mkroom *croom;
805.  
806.  	if(getbones()) return;
807.  	in_mklev = TRUE;
808.  	makelevel();
809.  	bound_digging();
810.  	in_mklev = FALSE;
811.  	if(!level.flags.is_maze_lev) {
812.  	    for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
813.  #ifdef SPECIALIZATION
814.  		topologize(croom, FALSE);
815.  #else
816.  		topologize(croom);
817.  #endif
818.  	}
819.  }
820.  
821.  void
822.  #ifdef SPECIALIZATION
823.  topologize(croom, do_ordinary)
824.  register struct mkroom *croom;
825.  boolean do_ordinary;
826.  #else
827.  topologize(croom)
828.  register struct mkroom *croom;
829.  #endif
830.  {
831.  	register int x, y, roomno = (croom - rooms) + ROOMOFFSET;
832.  	register int lowx = croom->lx, lowy = croom->ly;
833.  	register int hix = croom->hx, hiy = croom->hy;
834.  #ifdef SPECIALIZATION
835.  	register schar rtype = croom->rtype;
836.  #endif
837.  	register int subindex, nsubrooms = croom->nsubrooms;
838.  
839.  	/* skip the room if already done; i.e. a shop handled out of order */
840.  	/* also skip if this is non-rectangular (it _must_ be done already) */
841.  	if (levl[lowx][lowy].roomno == roomno || croom->irregular)
842.  	    return;
843.  #ifdef SPECIALIZATION
844.  # ifdef REINCARNATION
845.  	if (Is_rogue_level(&u.uz))
846.  	    do_ordinary = TRUE;		/* vision routine helper */
847.  # endif
848.  	if ((rtype != OROOM) || do_ordinary)
849.  #endif
850.  	{
851.  	    /* do innards first */
852.  	    for(x = lowx; x <= hix; x++)
853.  		for(y = lowy; y <= hiy; y++)
854.  #ifdef SPECIALIZATION
855.  		    if (rtype == OROOM)
856.  			levl[x][y].roomno = NO_ROOM;
857.  		    else
858.  #endif
859.  			levl[x][y].roomno = roomno;
860.  	    /* top and bottom edges */
861.  	    for(x = lowx-1; x <= hix+1; x++)
862.  		for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
863.  		    levl[x][y].edge = 1;
864.  		    if (levl[x][y].roomno)
865.  			levl[x][y].roomno = SHARED;
866.  		    else
867.  			levl[x][y].roomno = roomno;
868.  		}
869.  	    /* sides */
870.  	    for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
871.  		for(y = lowy; y <= hiy; y++) {
872.  		    levl[x][y].edge = 1;
873.  		    if (levl[x][y].roomno)
874.  			levl[x][y].roomno = SHARED;
875.  		    else
876.  			levl[x][y].roomno = roomno;
877.  		}
878.  	}
879.  	/* subrooms */
880.  	for (subindex = 0; subindex < nsubrooms; subindex++)
881.  #ifdef SPECIALIZATION
882.  		topologize(croom->sbrooms[subindex], (rtype != OROOM));
883.  #else
884.  		topologize(croom->sbrooms[subindex]);
885.  #endif
886.  }
887.  
888.  /* Find an unused room for a branch location. */
889.  static struct mkroom *
890.  find_branch_room(mp)
891.      coord *mp;
892.  {
893.      struct mkroom *croom = 0;
894.  
895.      if (nroom == 0) {
896.  	mazexy(mp);		/* already verifies location */
897.      } else {
898.  	/* not perfect - there may be only one stairway */
899.  	if(nroom > 2) {
900.  	    int tryct = 0;
901.  
902.  	    do
903.  		croom = &rooms[rn2(nroom)];
904.  	    while((croom == dnstairs_room || croom == upstairs_room ||
905.  		  croom->rtype != OROOM) && (++tryct < 100));
906.  	} else
907.  	    croom = &rooms[rn2(nroom)];
908.  
909.  	do {
910.  	    if (!somexy(croom, mp))
911.  		impossible("Can't place branch!");
912.  	} while(occupied(mp->x, mp->y) ||
913.  	    (levl[mp->x][mp->y].typ != CORR && levl[mp->x][mp->y].typ != ROOM));
914.      }
915.      return croom;
916.  }
917.  
918.  /* Find the room for (x,y).  Return NULL of not in a room. */
919.  static struct mkroom *
920.  pos_to_room(x, y)
921.      xchar x, y;
922.  {
923.      int i;
924.      struct mkroom *curr;
925.  
926.      for (curr = rooms, i = 0; i < nroom; curr++, i++)
927.  	if (inside_room(curr, x, y)) return curr;;
928.      return (struct mkroom *) 0;
929.  }
930.  
931.  
932.  /* If given a branch, randomly place a special stair or portal. */
933.  void
934.  place_branch(br, x, y)
935.  branch *br;	/* branch to place */
936.  xchar x, y;	/* location */
937.  {
938.  	coord	      m;
939.  	d_level	      *dest;
940.  	boolean	      make_stairs;
941.  	struct mkroom *br_room;
942.  
943.  	/*
944.  	 * Return immediately if there is no branch to make or we have
945.  	 * already made one.  This routine can be called twice when
946.  	 * a special level is loaded that specifies an SSTAIR location
947.  	 * as a favored spot for a branch.
948.  	 */
949.  	if (!br || made_branch) return;
950.  
951.  	if (!x) {	/* find random coordinates for branch */
952.  	    br_room = find_branch_room(&m);
953.  	    x = m.x;
954.  	    y = m.y;
955.  	} else {
956.  	    br_room = pos_to_room(x, y);
957.  	}
958.  
959.  	if (on_level(&br->end1, &u.uz)) {
960.  	    /* we're on end1 */
961.  	    make_stairs = br->type != BR_NO_END1;
962.  	    dest = &br->end2;
963.  	} else {
964.  	    /* we're on end2 */
965.  	    make_stairs = br->type != BR_NO_END2;
966.  	    dest = &br->end1;
967.  	}
968.  
969.  	if (br->type == BR_PORTAL) {
970.  	    mkportal(x, y, dest->dnum, dest->dlevel);
971.  	} else if (make_stairs) {
972.  	    sstairs.sx = x;
973.  	    sstairs.sy = y;
974.  	    sstairs.up = (char) on_level(&br->end1, &u.uz) ?
975.  					    br->end1_up : !br->end1_up;
976.  	    assign_level(&sstairs.tolev, dest);
977.  	    sstairs_room = br_room;
978.  
979.  	    levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
980.  	    levl[x][y].typ = STAIRS;
981.  	}
982.  	/*
983.  	 * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
984.  	 * make_stairs is false) since there is currently only one branch
985.  	 * per level, if we failed once, we're going to fail again on the
986.  	 * next call.
987.  	 */
988.  	made_branch = TRUE;
989.  }
990.  
991.  static boolean
992.  bydoor(x, y)
993.  register xchar x, y;
994.  {
995.  	register boolean tmp1, tmp2;
996.  
997.  	/* break up large expression to help some compilers */
998.  	tmp1 = (IS_DOOR(levl[x+1][y].typ) || levl[x+1][y].typ == SDOOR ||
999.  		IS_DOOR(levl[x-1][y].typ) || levl[x-1][y].typ == SDOOR);
1000. 	tmp2 = (IS_DOOR(levl[x][y+1].typ) || levl[x][y+1].typ == SDOOR ||
1001. 		IS_DOOR(levl[x][y-1].typ) || levl[x][y-1].typ == SDOOR);
1002. 	return(tmp1 || tmp2);
1003. }
1004. 
1005. /* see whether it is allowable to create a door at [x,y] */
1006. int
1007. okdoor(x,y)
1008. register xchar x, y;
1009. {
1010. 	register boolean near_door = bydoor(x, y);
1011. 
1012. 	return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&
1013. 			doorindex < DOORMAX && !near_door);
1014. }
1015. 
1016. void
1017. dodoor(x,y,aroom)
1018. register int x, y;
1019. register struct mkroom *aroom;
1020. {
1021. 	if(doorindex >= DOORMAX) {
1022. 		impossible("DOORMAX exceeded?");
1023. 		return;
1024. 	}
1025. 
1026. 	dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
1027. }
1028. 
1029. boolean
1030. occupied(x, y)
1031. register xchar x, y;
1032. {
1033. 	return(t_at(x, y) || levl[x][y].typ == STAIRS
1034. 		|| IS_FOUNTAIN(levl[x][y].typ)
1035. 		|| IS_THRONE(levl[x][y].typ)
1036. #ifdef SINKS
1037. 		|| IS_SINK(levl[x][y].typ)
1038. #endif
1039. 		|| levl[x][y].typ == ALTAR
1040. 		|| is_lava(x,y)
1041. 		|| is_pool(x,y)
1042. 		|| invocation_pos(x,y)
1043. 		);
1044. }
1045. 
1046. /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
1047. /* if tm != NULL, make trap at that location */
1048. void
1049. mktrap(num, mazeflag, croom, tm)
1050. register int num, mazeflag;
1051. register struct mkroom *croom;
1052. coord *tm;
1053. {
1054. 	register int kind;
1055. 	coord m;
1056. 
1057. 	/* no traps in pools */
1058. 	if (tm && is_pool(tm->x,tm->y)) return;
1059. 
1060. 	if (num > 0 && num < TRAPNUM) {
1061. 	    kind = num;
1062. #ifdef REINCARNATION
1063. 	} else if (Is_rogue_level(&u.uz)) {
1064. 	    switch (rn2(7)) {
1065. 		default: kind = BEAR_TRAP; break; /* 0 */
1066. 		case 1: kind = ARROW_TRAP; break;
1067. 		case 2: kind = DART_TRAP; break;
1068. 		case 3: kind = TRAPDOOR; break;
1069. 		case 4: kind = PIT; break;
1070. 		case 5: kind = SLP_GAS_TRAP; break;
1071. 		case 6: kind = RUST_TRAP; break;
1072. 	    }
1073. #endif
1074. 	} else if (Inhell && !rn2(5)) {
1075. 	    /* bias the frequency of fire traps in Gehennom */
1076. 	    kind = FIRE_TRAP;
1077. 	} else {
1078. 	    unsigned lvl = level_difficulty();
1079. 
1080. 	    do {
1081. 		kind = rnd(TRAPNUM-1);
1082. 		/* reject "too hard" traps */
1083. 		switch (kind) {
1084. 		    case LEVEL_TELEP:
1085. 		    case LANDMINE:
1086. 			if (lvl < 5) kind = NO_TRAP; break;
1087. 		    case SPIKED_PIT:
1088. #ifdef POLYSELF
1089. 		    case POLY_TRAP:
1090. #endif
1091. 			if (lvl < 6) kind = NO_TRAP; break;
1092. 		    case WEB:
1093. 		    case STATUE_TRAP:
1094. 			if (lvl < 7) kind = NO_TRAP; break;
1095. 		    case FIRE_TRAP:
1096. 			if (!Inhell) kind = NO_TRAP; break;
1097. 		}
1098. 	    } while (kind == NO_TRAP || kind == MAGIC_PORTAL);
1099. 	}
1100. 
1101. 	if (kind == TRAPDOOR && !Can_fall_thru(&u.uz)) kind = ROCKTRAP;
1102. 
1103. 	if (tm)
1104. 	    m = *tm;
1105. 	else {
1106. 	    register int tryct = 0;
1107. 
1108. 	    do {
1109. 		if (++tryct > 200)
1110. 		    return;
1111. 		if (mazeflag)
1112. 		    mazexy(&m);
1113. 		else if (!somexy(croom,&m))
1114. 		    return;
1115. 	    } while (occupied(m.x, m.y) || is_pool(m.x,m.y) ||
1116. 				     (sobj_at(BOULDER, m.x, m.y) &&
1117. 				      (kind == PIT || kind == SPIKED_PIT ||
1118. 				       kind == TRAPDOOR)));
1119. 	}
1120. 
1121. 	(void) maketrap(m.x, m.y, kind);
1122. 	if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y);
1123. }
1124. 
1125. void
1126. mkstairs(x, y, up, croom)
1127. xchar x, y;
1128. char  up;
1129. struct mkroom *croom;
1130. {
1131. 	if (! (x || y)) {
1132. 	    impossible("mkstairs:  bogus stair attempt at (%d,%d)", x, y);
1133. 	    return;
1134. 	}
1135. 
1136. 	/*
1137. 	 * We can't make a regular stair off an end of the dungeon.  This
1138. 	 * attempt can happen when a special level is placed at an end and
1139. 	 * has an up or down stair specified in its description file.
1140. 	 */
1141. 	if ((dunlev(&u.uz) == 1 && up) ||
1142. 			(dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up))
1143. 	    return;
1144. 
1145. 	if(up) {
1146. 		xupstair = x;
1147. 		yupstair = y;
1148. 		upstairs_room = croom;
1149. 	} else {
1150. 		xdnstair = x;
1151. 		ydnstair = y;
1152. 		dnstairs_room = croom;
1153. 	}
1154. 
1155. 	levl[x][y].typ = STAIRS;
1156. 	levl[x][y].ladder = up ? LA_UP : LA_DOWN;
1157. }
1158. 
1159. static
1160. void
1161. mkfount(mazeflag,croom)
1162. register int mazeflag;
1163. register struct mkroom *croom;
1164. {
1165. 	coord m;
1166. 	register int tryct = 0;
1167. 
1168. 	do {
1169. 	    if(++tryct > 200) return;
1170. 	    if(mazeflag)
1171. 		mazexy(&m);
1172. 	    else
1173. 		if (!somexy(croom, &m))
1174. 		    return;
1175. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1176. 
1177. 	/* Put a fountain at m.x, m.y */
1178. 	levl[m.x][m.y].typ = FOUNTAIN;
1179. 	/* Is it a "blessed" fountain? (affects drinking from fountain) */
1180. 	if(!rn2(7)) levl[m.x][m.y].blessedftn = 1;
1181. 
1182. 	level.flags.nfountains++;
1183. }
1184. 
1185. #ifdef SINKS
1186. static void
1187. mksink(croom)
1188. register struct mkroom *croom;
1189. {
1190. 	coord m;
1191. 	register int tryct = 0;
1192. 
1193. 	do {
1194. 	    if(++tryct > 200) return;
1195. 	    if (!somexy(croom, &m))
1196. 		return;
1197. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1198. 
1199. 	/* Put a sink at m.x, m.y */
1200. 	levl[m.x][m.y].typ = SINK;
1201. 
1202. 	level.flags.nsinks++;
1203. }
1204. #endif /* SINKS /**/
1205. 
1206. 
1207. static void
1208. mkaltar(croom)
1209. register struct mkroom *croom;
1210. {
1211. 	coord m;
1212. 	register int tryct = 0;
1213. 	aligntyp al;
1214. 
1215. 	if(croom->rtype != OROOM) return;
1216. 
1217. 	do {
1218. 	    if(++tryct > 200) return;
1219. 	    if (!somexy(croom, &m))
1220. 		return;
1221. 	} while(occupied(m.x, m.y) || bydoor(m.x, m.y));
1222. 
1223. 	/* Put an altar at m.x, m.y */
1224. 	levl[m.x][m.y].typ = ALTAR;
1225. 
1226. 	/* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
1227. 	al = rn2((int)A_LAWFUL+2) - 1;
1228. 	levl[m.x][m.y].altarmask = Align2amask( al );
1229. }
1230. 
1231. /*
1232.  * Major level transmutation: add a set of stairs (to the Sanctum) after
1233.  * an earthquake that leaves behind a a new topology, centered at inv_pos.
1234.  * Assumes there are no rooms within the invocation area and that inv_pos
1235.  * is not too close to the edge of the map.  Also assume the hero can see.
1236.  */
1237. void
1238. mkinvokearea()
1239. {
1240.     int dist;
1241.     xchar xmin = inv_pos.x, xmax = inv_pos.x;
1242.     xchar ymin = inv_pos.y, ymax = inv_pos.y;
1243.     register xchar i;
1244. 
1245.     pline("The floor shakes violently under you!");
1246.     pline("The walls around you begin to move and fall down!");
1247.     display_nhwindow(WIN_MESSAGE, TRUE);
1248. 
1249.     for(dist = 1; dist < 7; dist++) {
1250. 	xmin--; xmax++;
1251. 
1252. 	/* top and bottom */
1253. 	if(dist != 3) { /* the area is wider that it is high */
1254. 	    ymin--; ymax++;
1255. 	    for(i = xmin+1; i < xmax; i++) {
1256. 		mkinvpos(i, ymin, dist);
1257. 		mkinvpos(i, ymax, dist);
1258. 	    }
1259. 	}
1260. 
1261. 	/* left and right */
1262. 	for(i = ymin; i <= ymax; i++) {
1263. 	    mkinvpos(xmin, i, dist);
1264. 	    mkinvpos(xmax, i, dist);
1265. 	}
1266. 
1267. 	flush_screen(1);	/* make sure the new glyphs shows up */
1268. 	delay_output();
1269.     }
1270. 
1271.     You("are standing at the top of a stairwell leading down!");
1272.     mkstairs(u.ux, u.uy, 0, (struct mkroom *)0); /* down */
1273.     newsym(u.ux, u.uy);
1274.     vision_full_recalc = 1;	/* everything changed */
1275. }
1276. 
1277. /* Change level topology.  Messes with vision tables and ignores things like
1278.  * boulders in the name of a nice effect.  Vision will get fixed up again
1279.  * immediately after the effect is complete.
1280.  */
1281. static void
1282. mkinvpos(x,y,dist)
1283. xchar x,y;
1284. int dist;
1285. {
1286.     struct trap *ttmp;
1287.     register struct rm *lev = &levl[x][y];
1288. 
1289.     unblock_point(x,y);	/* make sure vision knows this location is open */
1290. 
1291.     /* fake out saved state */
1292.     lev->seen = FALSE;
1293.     lev->doormask = 0;
1294.     if(dist < 6) lev->lit = TRUE;
1295.     lev->waslit = TRUE;
1296.     lev->horizontal = FALSE;
1297.     viz_array[y][x] = (dist < 6 ) ?
1298. 	(IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */
1299. 	COULD_SEE;
1300. 
1301.     switch(dist) {
1302.     case 1: /* fire traps */
1303. 	lev->typ = ROOM;
1304. 	if (is_pool(x,y)) break;
1305. 	ttmp = maketrap(x, y, FIRE_TRAP);
1306. 	ttmp->tseen = TRUE;
1307. 	break;
1308.     case 2: /* lit room locations */
1309.     case 3:
1310.     case 6:
1311. 	if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
1312. 	lev->typ = ROOM;
1313. 	break;
1314.     case 4: /* pools (aka a wide moat) */
1315.     case 5:
1316. 	if ((ttmp = t_at(x,y)) != 0) deltrap(ttmp);
1317. 	lev->typ = MOAT;
1318. 	break;
1319.     default:
1320. 	impossible("mkinvpos called with dist %d", dist);
1321. 	break;
1322.     }
1323. 
1324.     /* display new value of position; could have a monster/object on it */
1325.     newsym(x,y);
1326. }
1327. 
1328. #ifdef MULDGN
1329. /*
1330.  * The portal to Ludios is special.  The entrance can only occur within a
1331.  * vault in the main dungeon at a depth greater than 10.  The Ludios branch
1332.  * structure reflects this by having a bogus "source" dungeon:  the value
1333.  * of n_dgns (thus, Is_branchlev() will never find it).
1334.  *
1335.  * Ludios will remain isolated until the branch is corrected by this function.
1336.  */
1337. static void
1338. mk_knox_portal(x, y)
1339. xchar x, y;
1340. {
1341. 	extern int n_dgns;		/* from dungeon.c */
1342. 	d_level *source;
1343. 	branch *br;
1344. 	xchar u_depth;
1345. 
1346. 	br = dungeon_branch("Fort Ludios");
1347. 	if (on_level(&knox_level, &br->end1)) {
1348. 	    source = &br->end2;
1349. 	} else {
1350. 	    /* disallow Knox branch on a level with one branch already */
1351. 	    if(Is_branchlev(&u.uz))
1352. 		return;
1353. 	    source = &br->end1;
1354. 	}
1355. 
1356. 	/* Already set or 2/3 chance of deferring until a later level. */
1357. 	if (source->dnum < n_dgns || (rn2(3)
1358. #ifdef WIZARD
1359. 				      && !wizard
1360. #endif
1361. 				      )) return;
1362. 
1363. 	if (! (u.uz.dnum == oracle_level.dnum	    /* in main dungeon */
1364. 		&& !at_dgn_entrance("The Quest")    /* but not Quest's entry */
1365. 		&& (u_depth = depth(&u.uz)) > 10    /* beneath 10 */
1366. 		&& u_depth < depth(&medusa_level))) /* and above Medusa */
1367. 	    return;
1368. 
1369. 	/* Adjust source to be current level and re-insert branch. */
1370. 	*source = u.uz;
1371. 	insert_branch(br, TRUE);
1372. 
1373. # ifdef DEBUG
1374. 	pline("Made knox portal.");
1375. # endif
1376. 	place_branch(br, x, y);
1377. }
1378. #endif
1379. 
1380. /*mklev.c*/