Fandom

Wikihack

Source:NetHack 3.2.0/sp lev.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to sp_lev.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/sp_lev.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.
1.    /*	SCCS Id: @(#)sp_lev.c	3.2	96/03/13	*/
2.    /*	Copyright (c) 1989 by Jean-Christophe Collet */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /*
6.     * This file contains the various functions that are related to the special
7.     * levels.
8.     * It contains also the special level loader.
9.     *
10.    */
11.   
12.   #include "hack.h"
13.   #include "dlb.h"
14.   /* #define DEBUG	/* uncomment to enable code debugging */
15.   
16.   #ifdef DEBUG
17.   # ifdef WIZARD
18.   #define debugpline	if (wizard) pline
19.   # else
20.   #define debugpline	pline
21.   # endif
22.   #endif
23.   
24.   #include "sp_lev.h"
25.   #include "rect.h"
26.   
27.   extern void FDECL(mkmap, (lev_init *));
28.   
29.   static void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
30.   static void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *));
31.   static void FDECL(create_trap, (trap *, struct mkroom *));
32.   static void FDECL(create_monster, (monster *, struct mkroom *));
33.   static void FDECL(create_object, (object *, struct mkroom *));
34.   static void FDECL(create_engraving, (engraving *,struct mkroom *));
35.   static void FDECL(create_stairs, (stair *, struct mkroom *));
36.   static void FDECL(create_altar, (altar *, struct mkroom *));
37.   static void FDECL(create_gold, (gold *, struct mkroom *));
38.   static void FDECL(create_feature, (int,int,struct mkroom *,int));
39.   static boolean FDECL(search_door, (struct mkroom *, xchar *, xchar *,
40.   					XCHAR_P, int));
41.   static void NDECL(fix_stair_rooms);
42.   static void FDECL(create_corridor, (corridor *));
43.   
44.   static boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
45.   					XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
46.   
47.   #define LEFT	1
48.   #define H_LEFT	2
49.   #define CENTER	3
50.   #define H_RIGHT	4
51.   #define RIGHT	5
52.   
53.   #define TOP	1
54.   #define BOTTOM	5
55.   
56.   #define sq(x) ((x)*(x))
57.   
58.   #define XLIM	4
59.   #define YLIM	3
60.   
61.   #define Fread	(void)dlb_fread
62.   #define Fgetc	(schar)dlb_fgetc
63.   #define New(type)		(type *) alloc(sizeof(type))
64.   #define NewTab(type, size)	(type **) alloc(sizeof(type *) * (unsigned)size)
65.   #define Free(ptr)		if(ptr) free((genericptr_t) (ptr))
66.   
67.   static NEARDATA walk walklist[50];
68.   extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
69.   
70.   static char Map[COLNO][ROWNO];
71.   static char robjects[10], rloc_x[10], rloc_y[10], rmonst[10];
72.   static aligntyp	ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
73.   static NEARDATA xchar xstart, ystart;
74.   static NEARDATA char xsize, ysize;
75.   
76.   static void FDECL(set_wall_property, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,int));
77.   static int NDECL(rnddoor);
78.   static int NDECL(rndtrap);
79.   static void FDECL(get_location, (schar *,schar *,int));
80.   static void FDECL(sp_lev_shuffle, (char *,char *,int));
81.   static void FDECL(light_region, (region *));
82.   static void FDECL(load_common_data, (dlb *,int));
83.   static void FDECL(load_one_monster, (dlb *,monster *));
84.   static void FDECL(load_one_object, (dlb *,object *));
85.   static void FDECL(load_one_engraving, (dlb *,engraving *));
86.   static boolean FDECL(load_rooms, (dlb *));
87.   static void FDECL(maze1xy, (coord *,int));
88.   static boolean FDECL(load_maze, (dlb *));
89.   static void FDECL(create_door, (room_door *, struct mkroom *));
90.   static void FDECL(free_rooms,(room **, int));
91.   static void FDECL(build_room, (room *, room*));
92.   
93.   char *lev_message = 0;
94.   lev_region *lregions = 0;
95.   int num_lregions = 0;
96.   lev_init init_lev;
97.   
98.   /*
99.    * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able
100.   */
101.  
102.  static void
103.  set_wall_property(x1,y1,x2,y2, prop)
104.  xchar x1, y1, x2, y2;
105.  int prop;
106.  {
107.  	register xchar x, y;
108.  
109.  	for(y = y1; y <= y2; y++)
110.  	    for(x = x1; x <= x2; x++)
111.  		if(IS_STWALL(levl[x][y].typ))
112.  		    levl[x][y].wall_info |= prop;
113.  }
114.  
115.  /*
116.   * Choose randomly the state (nodoor, open, closed or locked) for a door
117.   */
118.  static int
119.  rnddoor()
120.  {
121.  	int i = 1 << rn2(5);
122.  	i >>= 1;
123.  	return i;
124.  }
125.  
126.  /*
127.   * Select a random trap
128.   */
129.  static int
130.  rndtrap()
131.  {
132.  	int rtrap;
133.  
134.  	do {
135.  	    rtrap = rnd(TRAPNUM-1);
136.  	    switch (rtrap) {
137.  	     case HOLE:		/* no random holes on special levels */
138.  	     case MAGIC_PORTAL:	rtrap = NO_TRAP;
139.  				break;
140.  	     case TRAPDOOR:	if (!Can_dig_down(&u.uz)) rtrap = NO_TRAP;
141.  				break;
142.  	     case LEVEL_TELEP:
143.  	     case TELEP_TRAP:	if (level.flags.noteleport) rtrap = NO_TRAP;
144.  				break;
145.  	     case ROLLING_BOULDER_TRAP:
146.  	     case ROCKTRAP:	if (In_endgame(&u.uz)) rtrap = NO_TRAP;
147.  				break;
148.  	    }
149.  	} while (rtrap == NO_TRAP);
150.  	return rtrap;
151.  }
152.  
153.  /*
154.   * Coordinates in special level files are handled specially:
155.   *
156.   *	if x or y is -11, we generate a random coordinate.
157.   *	if x or y is between -1 and -10, we read one from the corresponding
158.   *	register (x0, x1, ... x9).
159.   *	if x or y is nonnegative, we convert it from relative to the local map
160.   *	to global coordinates.
161.   *	The "humidity" flag is used to insure that engravings aren't
162.   *	created underwater, or eels on dry land.
163.   */
164.  #define DRY	0x1
165.  #define WET	0x2
166.  
167.  static boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
168.  
169.  static void
170.  get_location(x, y, humidity)
171.  schar *x, *y;
172.  int humidity;
173.  {
174.  	int cpt = 0;
175.  
176.  	if (*x >= 0) {			/* normal locations */
177.  		*x += xstart;
178.  		*y += ystart;
179.  	} else if (*x > -11) {		/* special locations */
180.  		*y = ystart + rloc_y[ - *y - 1];
181.  		*x = xstart + rloc_x[ - *x - 1];
182.  	} else {			/* random location */
183.  	    do {
184.  		*x = xstart + rn2((int)xsize);
185.  		*y = ystart + rn2((int)ysize);
186.  		if (is_ok_location(*x,*y,humidity)) break;
187.  	    } while (++cpt < 100);
188.  	    if (cpt >= 100) {
189.  		register int xx, yy;
190.  		/* last try */
191.  		for (xx = 0; xx < xsize; xx++)
192.  		    for (yy = 0; yy < ysize; yy++) {
193.  			*x = xstart + xx;
194.  			*y = ystart + yy;
195.  			if (is_ok_location(*x,*y,humidity)) goto found_it;
196.  		    }
197.  		panic("get_location:  can't find a place!");
198.  	    }
199.  	}
200.  found_it:;
201.  
202.  	if (*x <= 0 || *x >= COLNO || *y < 0 || *y >= ROWNO) {
203.  	    impossible("get_location:  (%d,%d) out of bounds", *x, *y);
204.  	    *x = x_maze_max; *y = y_maze_max;
205.  	}
206.  }
207.  
208.  static boolean
209.  is_ok_location(x, y, humidity)
210.  register schar x, y;
211.  register int humidity;
212.  {
213.  	register int typ;
214.  
215.  	if (humidity & DRY) {
216.  	    typ = levl[x][y].typ;
217.  	    if (typ == ROOM || typ == AIR ||
218.  		    typ == CLOUD || typ == ICE || typ == CORR)
219.  		return TRUE;
220.  	}
221.  	if (humidity & WET) {
222.  	    if (is_pool(x,y) || is_lava(x,y))
223.  		return TRUE;
224.  	}
225.  	return FALSE;
226.  }
227.  
228.  /*
229.   * Shuffle the registers for locations, objects or monsters
230.   */
231.  
232.  static void
233.  sp_lev_shuffle(list1, list2, n)
234.  char list1[], list2[];
235.  int n;
236.  {
237.  	register int i, j;
238.  	register char k;
239.  
240.  	for (i = n - 1; i > 0; i--) {
241.  		if ((j = rn2(i + 1)) == i) continue;
242.  		k = list1[j];
243.  		list1[j] = list1[i];
244.  		list1[i] = k;
245.  		if (list2) {
246.  			k = list2[j];
247.  			list2[j] = list2[i];
248.  			list2[i] = k;
249.  		}
250.  	}
251.  }
252.  
253.  /*
254.   * Get a relative position inside a room.
255.   * negative values for x or y means RANDOM!
256.   */
257.  
258.  static void
259.  get_room_loc(x,y, croom)
260.  schar		*x, *y;
261.  struct mkroom	*croom;
262.  {
263.  	coord c;
264.  
265.  	if (*x <0 && *y <0) {
266.  		if (somexy(croom, &c)) {
267.  			*x = c.x;
268.  			*y = c.y;
269.  		} else
270.  		    panic("get_room_loc : can't find a place!");
271.  	} else {
272.  		if (*x < 0)
273.  		    *x = rn2(croom->hx - croom->lx + 1);
274.  		if (*y < 0)
275.  		    *y = rn2(croom->hy - croom->ly + 1);
276.  		*x += croom->lx;
277.  		*y += croom->ly;
278.  	}
279.  }
280.  
281.  /*
282.   * Get a relative position inside a room.
283.   * negative values for x or y means RANDOM!
284.   */
285.  
286.  static void
287.  get_free_room_loc(x,y, croom)
288.  schar		*x, *y;
289.  struct mkroom	*croom;
290.  {
291.  	schar try_x, try_y;
292.  	register int trycnt = 0;
293.  
294.  	do {
295.  	    try_x = *x,  try_y = *y;
296.  	    get_room_loc(&try_x, &try_y, croom);
297.  	} while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100);
298.  
299.  	if (trycnt > 100)
300.  	    panic("get_free_room_loc:  can't find a place!");
301.  	*x = try_x,  *y = try_y;
302.  }
303.  
304.  boolean
305.  check_room(lowx, ddx, lowy, ddy, vault)
306.  xchar *lowx, *ddx, *lowy, *ddy;
307.  boolean vault;
308.  {
309.  	register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy;
310.  	register struct rm *lev;
311.  	int xlim, ylim, ymax;
312.  
313.  	xlim = XLIM + (vault ? 1 : 0);
314.  	ylim = YLIM + (vault ? 1 : 0);
315.  	
316.  	if (*lowx < 3)		*lowx = 3;
317.  	if (*lowy < 2)		*lowy = 2;
318.  	if (hix > COLNO-3)	hix = COLNO-3;
319.  	if (hiy > ROWNO-3)	hiy = ROWNO-3;
320.  chk:
321.  	if (hix <= *lowx || hiy <= *lowy)	return FALSE;
322.  
323.  	/* check area around room (and make room smaller if necessary) */
324.  	for (x = *lowx - xlim; x<= hix + xlim; x++) {
325.  		if(x <= 0 || x >= COLNO) continue;
326.  		y = *lowy - ylim;	ymax = hiy + ylim;
327.  		if(y < 0) y = 0;
328.  		if(ymax >= ROWNO) ymax = (ROWNO-1);
329.  		lev = &levl[x][y];
330.  		for (; y <= ymax; y++) {
331.  			if (lev++->typ) {
332.  #ifdef DEBUG
333.  				if(!vault)
334.  				    debugpline("strange area [%d,%d] in check_room.",x,y);
335.  #endif
336.  				if (!rn2(3))	return FALSE;
337.  				if (x < *lowx)
338.  				    *lowx = x + xlim + 1;
339.  				else
340.  				    hix = x - xlim - 1;
341.  				if (y < *lowy)
342.  				    *lowy = y + ylim + 1;
343.  				else
344.  				    hiy = y - ylim - 1;
345.  				goto chk;
346.  			}
347.  		}
348.  	}
349.  	*ddx = hix - *lowx;
350.  	*ddy = hiy - *lowy;
351.  	return TRUE;
352.  }
353.  
354.  /*
355.   * Create a new room.
356.   * This is still very incomplete...
357.   */
358.  
359.  boolean
360.  create_room(x,y,w,h,xal,yal,rtype,rlit)
361.  xchar	x,y;
362.  xchar	w,h;
363.  xchar	xal,yal;
364.  xchar	rtype, rlit;
365.  {
366.  	xchar	xabs, yabs;
367.  	int	wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
368.  	NhRect	*r1 = 0, r2;
369.  	int	trycnt = 0;
370.  	boolean	vault = FALSE;
371.  	int	xlim = XLIM, ylim = YLIM;
372.  
373.  	if (rtype == -1)	/* Is the type random ? */
374.  	    rtype = OROOM;
375.  
376.  	if (rtype == VAULT) {
377.  		vault = TRUE;
378.  		xlim++;
379.  		ylim++;
380.  	}
381.  
382.  	/* on low levels the room is lit (usually) */
383.  	/* some other rooms may require lighting */
384.  
385.  	/* is light state random ? */
386.  	if (rlit == -1)
387.  	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
388.  
389.  	/*
390.  	 * Here we will try to create a room. If some parameters are
391.  	 * random we are willing to make several try before we give
392.  	 * it up.
393.  	 */
394.  	do {
395.  		xchar xborder, yborder;
396.  		wtmp = w; htmp = h;
397.  		xtmp = x; ytmp = y;
398.  		xaltmp = xal; yaltmp = yal;
399.  
400.  		/* First case : a totaly random room */
401.  
402.  		if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 &&
403.  		   yaltmp < 0) || vault) {
404.  			xchar hx, hy, lx, ly, dx, dy;
405.  			r1 = rnd_rect(); /* Get a random rectangle */
406.  
407.  			if (!r1) { /* No more free rectangles ! */
408.  #ifdef DEBUG
409.  				debugpline("No more rects...");
410.  #endif
411.  				return FALSE;
412.  			}
413.  			hx = r1->hx;
414.  			hy = r1->hy;
415.  			lx = r1->lx;
416.  			ly = r1->ly;
417.  			if (vault)
418.  			    dx = dy = 1;
419.  			else {
420.  				dx = 2 + rn2((hx-lx > 28) ? 12 : 8);
421.  				dy = 2 + rn2(4);
422.  				if(dx*dy > 50)
423.  				    dy = 50/dx;
424.  			}
425.  			xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1;
426.  			yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1;
427.  			if(hx-lx < dx + 3 + xborder ||
428.  			   hy-ly < dy + 3 + yborder) {
429.  				r1 = 0;
430.  				continue;
431.  			}
432.  			xabs = lx + (lx > 0 ? xlim : 3)
433.  			    + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1);
434.  			yabs = ly + (ly > 0 ? ylim : 2)
435.  			    + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1);
436.  			if (ly == 0 && hy >= (ROWNO-1) &&
437.  			    (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) {
438.  			    yabs = rn1(3, 2);
439.  			    if(nroom < 4 && dy>1) dy--;
440.  		        }
441.  			if (!check_room(&xabs, &dx, &yabs, &dy, vault)) {
442.  				r1 = 0;
443.  				continue;
444.  			}
445.  			wtmp = dx+1;
446.  			htmp = dy+1;
447.  			r2.lx = xabs-1; r2.ly = yabs-1;
448.  			r2.hx = xabs + wtmp;
449.  			r2.hy = yabs + htmp;
450.  		} else {	/* Only some parameters are random */
451.  			int rndpos = 0;
452.  			if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
453.  				xtmp = rnd(5);
454.  				ytmp = rnd(5);
455.  				rndpos = 1;
456.  			}
457.  			if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */
458.  				wtmp = rn1(15, 3);
459.  				htmp = rn1(8, 2);
460.  			}
461.  			if (xaltmp == -1) /* Horizontal alignment is RANDOM */
462.  			    xaltmp = rnd(3);
463.  			if (yaltmp == -1) /* Vertical alignment is RANDOM */
464.  			    yaltmp = rnd(3);
465.  
466.  			/* Try to generate real (absolute) coordinates here! */
467.  			
468.  			xabs = (((xtmp-1) * COLNO) / 5) + 1;
469.  			yabs = (((ytmp-1) * ROWNO) / 5) + 1;
470.  			switch (xaltmp) {
471.  			      case LEFT:
472.  				break;
473.  			      case RIGHT:
474.  				xabs += (COLNO / 5) - wtmp;
475.  				break;
476.  			      case CENTER:
477.  				xabs += ((COLNO / 5) - wtmp) / 2;
478.  				break;
479.  			}
480.  			switch (yaltmp) {
481.  			      case TOP:
482.  				break;
483.  			      case BOTTOM:
484.  				yabs += (ROWNO / 5) - htmp;
485.  				break;
486.  			      case CENTER:
487.  				yabs += ((ROWNO / 5) - htmp) / 2;
488.  				break;
489.  			}
490.  			
491.  			if (xabs + wtmp - 1 > COLNO - 2)
492.  			    xabs = COLNO - wtmp - 3;
493.  			
494.  			if (xabs < 2)
495.  			    xabs = 2;
496.  			
497.  			if (yabs + htmp - 1> ROWNO - 2)
498.  			    yabs = ROWNO - htmp - 3;
499.  
500.  			if (yabs < 2)
501.  			    yabs = 2;
502.  			/* Try to find a rectangle that fit our room ! */
503.  
504.  			r2.lx = xabs-1; r2.ly = yabs-1;
505.  			r2.hx = xabs + wtmp + rndpos;
506.  			r2.hy = yabs + htmp + rndpos;
507.  			r1 = get_rect(&r2);
508.  		}
509.  	} while (++trycnt <= 100 && !r1);
510.  	if (!r1) {	/* creation of room failed ? */
511.  		return FALSE;
512.  	}
513.  	split_rects(r1, &r2);
514.  
515.  	if (!vault) {
516.  		smeq[nroom] = nroom;
517.  		add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1,
518.  			 rlit, rtype, FALSE);
519.  	} else {
520.  		rooms[nroom].lx = xabs;
521.  		rooms[nroom].ly = yabs;
522.  	}
523.  	return TRUE;
524.  }
525.  
526.  /*
527.   * Create a subroom in room proom at pos x,y with width w & height h.
528.   * x & y are relative to the parent room.
529.   */
530.  
531.  static boolean
532.  create_subroom(proom, x, y, w,  h, rtype, rlit)
533.  struct mkroom *proom;
534.  xchar x,y;
535.  xchar w,h;
536.  xchar rtype, rlit;
537.  {
538.  	xchar width, height;
539.  
540.  	width = proom->hx - proom->lx + 1;
541.  	height = proom->hy - proom->ly + 1;
542.  
543.  	/* There is a minimum size for the parent room */
544.  	if (width < 4 || height < 4)
545.  	    return FALSE;
546.  
547.  	/* Check for random position, size, etc... */
548.  
549.  	if (w == -1)
550.  	    w = rnd(width - 3);
551.  	if (h == -1)
552.  	    h = rnd(height - 3);
553.  	if (x == -1)
554.  	    x = rnd(width - w - 1) - 1;
555.  	if (y == -1)
556.  	    y = rnd(height - h - 1) - 1;
557.  	if (x == 1)
558.  	    x = 0;
559.  	if (y == 1)
560.  	    y = 0;
561.  	if ((x + w + 1) == width)
562.  	    x++;
563.  	if ((y + h + 1) == height)
564.  	    y++;
565.  	if (rtype == -1)
566.  	    rtype = OROOM;
567.  	if (rlit == -1)
568.  	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
569.  	add_subroom(proom, proom->lx + x, proom->ly + y,
570.  		    proom->lx + x + w - 1, proom->ly + y + h - 1,
571.  		    rlit, rtype, FALSE);
572.  	return TRUE;
573.  }
574.  
575.  /*
576.   * Create a new door in a room.
577.   * It's placed on a wall (north, south, east or west).
578.   */
579.  
580.  static void
581.  create_door(dd, broom)
582.  room_door *dd;
583.  struct mkroom *broom;
584.  {
585.  	int	x, y;
586.  	int	trycnt = 0;
587.  
588.  	if (dd->secret == -1)
589.  	    dd->secret = rn2(2);
590.  
591.  	if (dd->mask == -1) {
592.  		/* is it a locked door, closed, or a doorway? */
593.  		if (!dd->secret) {
594.  			if(!rn2(3)) {
595.  				if(!rn2(5))
596.  				    dd->mask = D_ISOPEN;
597.  				else if(!rn2(6))
598.  				    dd->mask = D_LOCKED;
599.  				else
600.  				    dd->mask = D_CLOSED;
601.  				if (dd->mask != D_ISOPEN && !rn2(25))
602.  				    dd->mask |= D_TRAPPED;
603.  			} else
604.  			    dd->mask = D_NODOOR;
605.  		} else {
606.  			if(!rn2(5))	dd->mask = D_LOCKED;
607.  			else		dd->mask = D_CLOSED;
608.  
609.  			if(!rn2(20)) dd->mask |= D_TRAPPED;
610.  		}
611.  	}
612.  
613.  	do {
614.  		register int dwall, dpos;
615.  
616.  		dwall = dd->wall;
617.  		if (dwall == -1)	/* The wall is RANDOM */
618.  		    dwall = 1 << rn2(4);
619.  
620.  		dpos = dd->pos;
621.  		if (dpos == -1)	/* The position is RANDOM */
622.  		    dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?
623.  			    (broom->hy - broom->ly) : (broom->hx - broom->lx));
624.  		
625.  		/* Convert wall and pos into an absolute coordinate! */
626.  		
627.  		switch (dwall) {
628.  		      case W_NORTH:
629.  			y = broom->ly - 1;
630.  			x = broom->lx + dpos;
631.  			break;
632.  		      case W_SOUTH:
633.  			y = broom->hy + 1;
634.  			x = broom->lx + dpos;
635.  			break;
636.  		      case W_WEST:
637.  			x = broom->lx - 1;
638.  			y = broom->ly + dpos;
639.  			break;
640.  		      case W_EAST:
641.  			x = broom->hx + 1;
642.  			y = broom->ly + dpos;
643.  			break;
644.  		      default:
645.  			x = y = 0;
646.  			panic("create_door: No wall for door!");
647.  			break;
648.  		}
649.  		if (okdoor(x,y))
650.  		    break;
651.  	} while (++trycnt <= 100);
652.  	if (trycnt > 100) {
653.  		impossible("create_door: Can't find a proper place!");
654.  		return;
655.  	}
656.  	add_door(x,y,broom);
657.  	levl[x][y].typ = (dd->secret ? SDOOR : DOOR);
658.  	levl[x][y].doormask = dd->mask;
659.  }
660.  
661.  /*
662.   * Create a secret door in croom on any one of the specified walls.
663.   */
664.  void
665.  create_secret_door(croom, walls)
666.      struct mkroom *croom;
667.      xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
668.  {
669.      xchar sx, sy; /* location of the secret door */
670.      int count;
671.  
672.      for(count = 0; count < 100; count++) {
673.  	sx = rn1(croom->hx - croom->lx + 1, croom->lx);
674.  	sy = rn1(croom->hy - croom->ly + 1, croom->ly);
675.  
676.  	switch(rn2(4)) {
677.  	case 0:  /* top */
678.  	    if(!(walls & W_NORTH)) continue;
679.  	    sy = croom->ly-1; break;
680.  	case 1: /* bottom */
681.  	    if(!(walls & W_SOUTH)) continue;
682.  	    sy = croom->hy+1; break;
683.  	case 2: /* left */
684.  	    if(!(walls & W_EAST)) continue;
685.  	    sx = croom->lx-1; break;
686.  	case 3: /* right */
687.  	    if(!(walls & W_WEST)) continue;
688.  	    sx = croom->hx+1; break;
689.  	}
690.  
691.  	if(okdoor(sx,sy)) {
692.  	    levl[sx][sy].typ = SDOOR;
693.  	    levl[sx][sy].doormask = D_CLOSED;
694.  	    add_door(sx,sy,croom);
695.  	    return;
696.  	}
697.      }
698.  
699.      impossible("couldn't create secret door on any walls 0x%x", walls);
700.  }
701.  
702.  /*
703.   * Create a trap in a room.
704.   */
705.  
706.  static void
707.  create_trap(t,croom)
708.  trap	*t;
709.  struct mkroom	*croom;
710.  {
711.      schar	x,y;
712.      coord	tm;
713.  
714.      if (rn2(100) < t->chance) {
715.  	x = t->x;
716.  	y = t->y;
717.  	if (croom)
718.  	    get_free_room_loc(&x, &y, croom);
719.  	else
720.  	    get_location(&x, &y, DRY);
721.  
722.  	tm.x = x;
723.  	tm.y = y;
724.  
725.  	mktrap(t->type, 1, (struct mkroom*) 0, &tm);
726.      }
727.  }
728.  
729.  /*
730.   * Create a monster in a room.
731.   */
732.  
733.  static void
734.  create_monster(m,croom)
735.  monster	*m;
736.  struct mkroom	*croom;
737.  {
738.  	struct monst	*mtmp;
739.  	schar		x,y;
740.  	char		class;
741.  	aligntyp	amask;
742.  	struct permonst *pm;
743.  
744.  	if (m->class >= 0)
745.  	    class = (char) def_char_to_monclass((char)m->class);
746.  	else if (m->class > -11)
747.  	    class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
748.  	else
749.  	    class = 0;
750.  
751.  	if (class == MAXMCLASSES)
752.  	    panic("create_monster: unknown monster class '%c'", m->class);
753.  
754.  	amask = (m->align <= -11) ? induced_align(80) :
755.  	    (m->align < 0 ? ralign[-m->align-1] : m->align);
756.  
757.  	if (!class)
758.  	    pm = (struct permonst *) 0;
759.  	else if (m->id != NON_PM) {
760.  	    if (flags.female && Role_is('E') && m->id == PM_EARENDIL)
761.  		m->id = PM_ELWING;
762.  	    pm = &mons[m->id];
763.  	    if ((pm->geno & G_UNIQ) &&
764.  			(mvitals[monsndx(pm)].mvflags & G_EXTINCT))
765.  		goto m_done;
766.  	} else {
767.  	    pm = mkclass(class,G_NOGEN);
768.  	    /* if we can't get class for a specific monster type,
769.  	       it means, that it's extinct, genocided, or unique,
770.  	       and shouldn't be created. */
771.  	    if (!pm) goto m_done;	/* release memory before returning */
772.  	}
773.  
774.  	x = m->x;
775.  	y = m->y;
776.  	if (croom)
777.  	    get_room_loc(&x, &y, croom);
778.  	else {
779.  	    if (!pm || !is_swimmer(pm))
780.  		get_location(&x, &y, DRY);
781.  	    else if (pm->mlet == S_EEL)
782.  		get_location(&x, &y, WET);
783.  	    else
784.  		get_location(&x, &y, DRY|WET);
785.  	}
786.  
787.  
788.  	if(m->align != -12)
789.  	    mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
790.  	else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
791.  	         mtmp = mk_mplayer(pm, x, y, FALSE);
792.  	else mtmp = makemon(pm, x, y);
793.  
794.  	if (mtmp) {
795.  	    /* handle specific attributes for some special monsters */
796.  	    if (m->name.str) mtmp = christen_monst(mtmp, m->name.str);
797.  
798.  	    /*
799.  	     * This is currently hardwired for mimics only.  It should
800.  	     * eventually be expanded.
801.  	     */
802.  	    if (m->appear_as.str && mtmp->data->mlet == S_MIMIC) {
803.  		int i;
804.  
805.  		switch (m->appear) {
806.  		    case M_AP_NOTHING:
807.  			impossible(
808.  		"create_monster: mon has an appearance, \"%s\", but no type",
809.  				m->appear_as.str);
810.  			break;
811.  
812.  		    case M_AP_FURNITURE:
813.  			for (i = 0; i < MAXPCHARS; i++)
814.  			    if (!strcmp(defsyms[i].explanation,
815.  					m->appear_as.str))
816.  				break;
817.  			if (i == MAXPCHARS) {
818.  			    impossible(
819.  				"create_monster: can't find feature \"%s\"",
820.  				m->appear_as.str);
821.  			} else {
822.  			    mtmp->m_ap_type = M_AP_FURNITURE;
823.  			    mtmp->mappearance = i;
824.  			}
825.  			break;
826.  
827.  		    case M_AP_OBJECT:
828.  			for (i = 0; i < NUM_OBJECTS; i++)
829.  			    if (!strcmp(OBJ_NAME(objects[i]),
830.  					m->appear_as.str))
831.  				break;
832.  			if (i == NUM_OBJECTS) {
833.  			    impossible(
834.  				"create_monster: can't find object \"%s\"",
835.  				m->appear_as.str);
836.  			} else {
837.  			    mtmp->m_ap_type = M_AP_OBJECT;
838.  			    mtmp->mappearance = i;
839.  			}
840.  			break;
841.  
842.  		    case M_AP_MONSTER:
843.  			/* note: mimics don't appear as monsters! */
844.  			/*	 (but chameleons can :-)	  */
845.  		    default:
846.  			impossible(
847.  		"create_monster: unimplemented mon appear type [%d,\"%s\"]",
848.  				m->appear, m->appear_as.str);
849.  			break;
850.  		}
851.  		if (does_block(x, y, &levl[x][y]))
852.  		    block_point(x, y);
853.  	    }
854.  
855.  	    if (m->peaceful >= 0) {
856.  		mtmp->mpeaceful = m->peaceful;
857.  		/* changed mpeaceful again; have to reset malign */
858.  		set_malign(mtmp);
859.  	    }
860.  	    if (m->asleep >= 0) {
861.  #ifdef UNIXPC
862.  		/* optimizer bug strikes again */
863.  		if (m->asleep)
864.  			mtmp->msleep = TRUE;
865.  		else
866.  			mtmp->msleep = FALSE;
867.  #else
868.  		mtmp->msleep = m->asleep;
869.  #endif
870.  	    }
871.  	}
872.  
873.   m_done:
874.  	Free(m->name.str);
875.  	Free(m->appear_as.str);
876.  }
877.  
878.  /*
879.   * Create an object in a room.
880.   */
881.  
882.  static void
883.  create_object(o,croom)
884.  object	*o;
885.  struct mkroom	*croom;
886.  {
887.  	struct obj	*otmp;
888.  	schar	x,y;
889.  	char	c;
890.  
891.  	x = o->x; y = o->y;
892.  	if (croom)
893.  	    get_room_loc(&x, &y, croom);
894.  	else
895.  	    get_location(&x, &y, DRY);
896.  
897.  	if (o->class >= 0)
898.  	    c = o->class;
899.  	else if (o->class > -11)
900.  	    c = robjects[ -(o->class+1)];
901.  	else
902.  	    c = 0;
903.  
904.  	if (!c)
905.  	    otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
906.  	else if (o->id != -1)
907.  	    otmp = mksobj_at(o->id, x, y, TRUE);
908.  	else {
909.  	    /*
910.  	     * The special levels are compiled with the default "text" object
911.  	     * class characters.  We must convert them to the internal format.
912.  	     */
913.  	    char oclass = (char) def_char_to_objclass(c);
914.  
915.  	    if (oclass == MAXOCLASSES)
916.  		panic("create_object:  unexpected object class '%c'",c);
917.  	    otmp = mkobj_at(oclass, x, y, TRUE);
918.  	}
919.  
920.  	if (o->spe != -127)	/* That means NOT RANDOM! */
921.  	    otmp->spe = o->spe;
922.  
923.  	switch (o->curse_state) {
924.  	      case 1:	bless(otmp); break; /* BLESSED */
925.  	      case 2:	unbless(otmp); uncurse(otmp); break; /* uncursed */
926.  	      case 3:	curse(otmp); break; /* CURSED */
927.  	      default:	break;	/* Otherwise it's random and we're happy
928.  				 * with what mkobj gave us! */
929.  	}
930.  
931.  	/*	corpsenm is "empty" if -1, random if -2, otherwise specific */
932.  	if (o->corpsenm == NON_PM - 1) otmp->corpsenm = rndmonnum();
933.  	else if (o->corpsenm != NON_PM) otmp->corpsenm = o->corpsenm;
934.  
935.  	/* assume we wouldn't be given an egg corpsenm unless it was
936.  	   hatchable */
937.  	if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
938.  	    if (dead_species(otmp->otyp, TRUE))
939.  		kill_egg(otmp);	/* make sure nothing hatches */
940.  	    else
941.  		attach_egg_hatch_timeout(otmp);	/* attach new hatch timeout */
942.  
943.  	if (o->name.str) {	/* Give a name to that object */
944.  	    otmp = oname(otmp, o->name.str);
945.  	    free((genericptr_t) o->name.str);
946.  	}
947.  
948.  	switch(o->containment) {
949.  	    static struct obj *container = 0;
950.  
951.  	    /* contents */
952.  	    case 1:
953.  		if (!container) {
954.  		    impossible("create_object: no container");
955.  		    break;
956.  		}
957.  		remove_object(otmp);
958.  		add_to_container(container, otmp);
959.  		return;
960.  	    /* container */
961.  	    case 2:
962.  		delete_contents(otmp);
963.  		container = otmp;
964.  		return;
965.  	    /* nothing */
966.  	    case 0: break;
967.  
968.  	    default: impossible("containment type %d?", (int) o->containment);
969.  	}
970.  	stackobj(otmp);
971.  }
972.  
973.  /*
974.   * Randomly place a specific engraving, then release its memory.
975.   */
976.  static void
977.  create_engraving(e, croom)
978.  engraving *e;
979.  struct mkroom *croom;
980.  {
981.  	xchar x, y;
982.  
983.  	x = e->x,  y = e->y;
984.  	if (croom)
985.  	    get_room_loc(&x, &y, croom);
986.  	else
987.  	    get_location(&x, &y, DRY);
988.  
989.  	make_engr_at(x, y, e->engr.str, 0L, e->etype);
990.  	free((genericptr_t) e->engr.str);
991.  }
992.  
993.  /*
994.   * Create stairs in a room.
995.   *
996.   */
997.  
998.  static void
999.  create_stairs(s,croom)
1000. stair	*s;
1001. struct mkroom	*croom;
1002. {
1003. 	schar		x,y;
1004. 
1005. 	x = s->x; y = s->y;
1006. 	get_free_room_loc(&x, &y, croom);
1007. 	mkstairs(x,y,(char)s->up, croom);
1008. }
1009. 
1010. /*
1011.  * Create an altar in a room.
1012.  */
1013. 
1014. static void
1015. create_altar(a, croom)
1016. 	altar		*a;
1017. 	struct mkroom	*croom;
1018. {
1019. 	schar		sproom,x,y;
1020. 	aligntyp	amask;
1021. 	boolean		croom_is_temple = TRUE;
1022. 
1023. 	x = a->x; y = a->y;
1024. 
1025. 	if (croom) {
1026. 	    get_free_room_loc(&x, &y, croom);
1027. 	    if (croom->rtype != TEMPLE)
1028. 		croom_is_temple = FALSE;
1029. 	} else {
1030. 	    get_location(&x, &y, DRY);
1031. 	    if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
1032. 		croom = &rooms[sproom - ROOMOFFSET];
1033. 	    else
1034. 		croom_is_temple = FALSE;
1035. 	}
1036. 
1037. 	a->x = x;
1038. 	a->y = y;
1039. 
1040. 	/* Is the alignment random ?
1041. 	 * If so, it's an 80% chance that the altar will be co-aligned.
1042. 	 *
1043. 	 * The alignment is encoded as amask values instead of alignment
1044. 	 * values to avoid conflicting with the rest of the encoding,
1045. 	 * shared by many other parts of the special level code.
1046. 	 */
1047. 
1048. 	amask = (a->align == -11) ? induced_align(80) :
1049. 	    (a->align < 0 ? ralign[-a->align-1] : a->align);
1050. 
1051. 	levl[x][y].typ = ALTAR;
1052. 	levl[x][y].altarmask = amask;
1053. 
1054. 	if (a->shrine == -11) a->shrine = rn2(1);  /* handle random case */
1055. 
1056. 	if (!croom_is_temple || !a->shrine) return;
1057. 
1058. 	if (a->shrine) {	/* Is it a shrine  or sanctum? */
1059. 	    priestini(&u.uz, croom, x, y, (a->shrine > 1));
1060. 	    levl[x][y].altarmask |= AM_SHRINE;
1061. 	    level.flags.has_temple = TRUE;
1062. 	}
1063. }
1064. 
1065. /*
1066.  * Create a gold pile in a room.
1067.  */
1068. 
1069. static void
1070. create_gold(g,croom)
1071. gold *g;
1072. struct mkroom	*croom;
1073. {
1074. 	schar		x,y;
1075. 
1076. 	x = g->x; y= g->y;
1077. 	if (croom)
1078. 	    get_room_loc(&x, &y, croom);
1079. 	else
1080. 	    get_location(&x, &y, DRY);
1081. 
1082. 	if (g->amount == -1)
1083. 	    g->amount = rnd(200);
1084. 	mkgold((long) g->amount, x, y);
1085. }
1086. 
1087. /*
1088.  * Create a feature (e.g a fountain) in a room.
1089.  */
1090. 
1091. static void
1092. create_feature(fx, fy, croom, typ)
1093. int		fx, fy;
1094. struct mkroom	*croom;
1095. int		typ;
1096. {
1097. 	schar		x,y;
1098. 	int		trycnt = 0;
1099. 
1100. 	x = fx;  y = fy;
1101. 	if (croom) {
1102. 	    if (x < 0 && y < 0)
1103. 		do {
1104. 		    x = -1;  y = -1;
1105. 		    get_room_loc(&x, &y, croom);
1106. 		} while (++trycnt <= 200 && occupied(x,y));
1107. 	    else
1108. 		get_room_loc(&x, &y, croom);
1109. 	    if(trycnt > 200)
1110. 		return;
1111. 	} else {
1112. 	    get_location(&x, &y, DRY);
1113. 	}
1114. 	levl[x][y].typ = typ;
1115. 	if (typ == FOUNTAIN)
1116. 	    level.flags.nfountains++;
1117. 	else if (typ == SINK)
1118. 	    level.flags.nsinks++;
1119. }
1120. 
1121. /*
1122.  * Search for a door in a room on a specified wall.
1123.  */
1124. 
1125. static boolean
1126. search_door(croom,x,y,wall,cnt)
1127. struct mkroom *croom;
1128. xchar *x, *y;
1129. xchar wall;
1130. int cnt;
1131. {
1132. 	int dx, dy;
1133. 	int xx,yy;
1134. 
1135. 	switch(wall) {
1136. 	      case W_NORTH:
1137. 		dy = 0; dx = 1;
1138. 		xx = croom->lx;
1139. 		yy = croom->hy + 1;
1140. 		break;
1141. 	      case W_SOUTH:
1142. 		dy = 0; dx = 1;
1143. 		xx = croom->lx;
1144. 		yy = croom->ly - 1;
1145. 		break;
1146. 	      case W_EAST:
1147. 		dy = 1; dx = 0;
1148. 		xx = croom->hx + 1;
1149. 		yy = croom->ly;
1150. 		break;
1151. 	      case W_WEST:
1152. 		dy = 1; dx = 0;
1153. 		xx = croom->lx - 1;
1154. 		yy = croom->ly;
1155. 		break;
1156. 	      default:
1157. 		dx = dy = xx = yy = 0;
1158. 		panic("search_door: Bad wall!");
1159. 		break;
1160. 	}
1161. 	while (xx <= croom->hx+1 && yy <= croom->hy+1) {
1162. 		if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
1163. 			*x = xx;
1164. 			*y = yy;
1165. 			if (cnt-- <= 0)
1166. 			    return TRUE;
1167. 		}
1168. 		xx += dx;
1169. 		yy += dy;
1170. 	}
1171. 	return FALSE;
1172. }
1173. 
1174. /*
1175.  * Dig a corridor between two points.
1176.  */
1177. 
1178. boolean
1179. dig_corridor(org,dest,nxcor,ftyp,btyp)
1180. coord *org, *dest;
1181. boolean nxcor;
1182. schar ftyp, btyp;
1183. {
1184. 	register int dx=0, dy=0, dix, diy, cct;
1185. 	register struct rm *crm;
1186. 	register int tx, ty, xx, yy;
1187. 
1188. 	xx = org->x;  yy = org->y;
1189. 	tx = dest->x; ty = dest->y;
1190. 	if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 ||
1191. 	    xx > COLNO-1 || tx > COLNO-1 ||
1192. 	    yy > ROWNO-1 || ty > ROWNO-1) {
1193. #ifdef DEBUG
1194. 		debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).",
1195. 			   xx,yy,tx,ty);
1196. #endif
1197. 		return FALSE;
1198. 	}
1199. 	if (tx > xx)		dx = 1;
1200. 	else if (ty > yy)	dy = 1;
1201. 	else if (tx < xx)	dx = -1;
1202. 	else			dy = -1;
1203. 	
1204. 	xx -= dx;
1205. 	yy -= dy;
1206. 	cct = 0;
1207. 	while(xx != tx || yy != ty) {
1208. 	    /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
1209. 	    if(cct++ > 500 || (nxcor && !rn2(35)))
1210. 		return FALSE;
1211. 
1212. 	    xx += dx;
1213. 	    yy += dy;
1214. 
1215. 	    if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1)
1216. 		return FALSE;		/* impossible */
1217. 
1218. 	    crm = &levl[xx][yy];
1219. 	    if(crm->typ == btyp) {
1220. 		if(ftyp != CORR || rn2(100)) {
1221. 			crm->typ = ftyp;
1222. 			if(nxcor && !rn2(50))
1223. 				(void) mksobj_at(BOULDER, xx, yy, TRUE);
1224. 		} else {
1225. 			crm->typ = SCORR;
1226. 		}
1227. 	    } else
1228. 	    if(crm->typ != ftyp && crm->typ != SCORR) {
1229. 		/* strange ... */
1230. 		return FALSE;
1231. 	    }
1232. 
1233. 	    /* find next corridor position */
1234. 	    dix = abs(xx-tx);
1235. 	    diy = abs(yy-ty);
1236. 
1237. 	    /* do we have to change direction ? */
1238. 	    if(dy && dix > diy) {
1239. 		register int ddx = (xx > tx) ? -1 : 1;
1240. 
1241. 		crm = &levl[xx+ddx][yy];
1242. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
1243. 		    dx = ddx;
1244. 		    dy = 0;
1245. 		    continue;
1246. 		}
1247. 	    } else if(dx && diy > dix) {
1248. 		register int ddy = (yy > ty) ? -1 : 1;
1249. 
1250. 		crm = &levl[xx][yy+ddy];
1251. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
1252. 		    dy = ddy;
1253. 		    dx = 0;
1254. 		    continue;
1255. 		}
1256. 	    }
1257. 
1258. 	    /* continue straight on? */
1259. 	    crm = &levl[xx+dx][yy+dy];
1260. 	    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
1261. 		continue;
1262. 
1263. 	    /* no, what must we do now?? */
1264. 	    if(dx) {
1265. 		dx = 0;
1266. 		dy = (ty < yy) ? -1 : 1;
1267. 	    } else {
1268. 		dy = 0;
1269. 		dx = (tx < xx) ? -1 : 1;
1270. 	    }
1271. 	    crm = &levl[xx+dx][yy+dy];
1272. 	    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
1273. 		continue;
1274. 	    dy = -dy;
1275. 	    dx = -dx;
1276. 	}
1277. 	return TRUE;
1278. }
1279. 
1280. /*
1281.  * Disgusting hack: since special levels have their rooms filled before
1282.  * sorting the rooms, we have to re-arrange the speed values upstairs_room
1283.  * and dnstairs_room after the rooms have been sorted.  On normal levels,
1284.  * stairs don't get created until _after_ sorting takes place.
1285.  */
1286. static void
1287. fix_stair_rooms()
1288. {
1289.     register i;
1290.     register struct mkroom *croom;
1291. 
1292.     if(xdnstair &&
1293.        !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) &&
1294. 	 (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) {
1295. 	for(i=0; i < nroom; i++) {
1296. 	    croom = &rooms[i];
1297. 	    if((croom->lx <= xdnstair && xdnstair <= croom->hx) &&
1298. 	       (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
1299. 		dnstairs_room = croom;
1300. 		break;
1301. 	    }
1302. 	}
1303. 	if(i == nroom)
1304. 	    panic("Couldn't find dnstair room in fix_stair_rooms!");
1305.     }
1306.     if(xupstair &&
1307.        !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) &&
1308. 	 (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) {
1309. 	for(i=0; i < nroom; i++) {
1310. 	    croom = &rooms[i];
1311. 	    if((croom->lx <= xupstair && xupstair <= croom->hx) &&
1312. 	       (croom->ly <= yupstair && yupstair <= croom->hy)) {
1313. 		upstairs_room = croom;
1314. 		break;
1315. 	    }
1316. 	}
1317. 	if(i == nroom)
1318. 	    panic("Couldn't find upstair room in fix_stair_rooms!");
1319.     }
1320. }
1321. 
1322. /*
1323.  * Corridors always start from a door. But it can end anywhere...
1324.  * Basically we search for door coordinates or for endpoints coordinates
1325.  * (from a distance).
1326.  */
1327. 
1328. static void
1329. create_corridor(c)
1330. corridor	*c;
1331. {
1332. 	coord org, dest;
1333. 
1334. 	if (c->src.room == -1) {
1335. 		sort_rooms();
1336. 		fix_stair_rooms();
1337. 		makecorridors();
1338. 		return;
1339. 	}
1340. 
1341. 	if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall,
1342. 			 c->src.door))
1343. 	    return;
1344. 
1345. 	if (c->dest.room != -1) {
1346. 		if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y,
1347. 				c->dest.wall, c->dest.door))
1348. 		    return;
1349. 		switch(c->src.wall) {
1350. 		      case W_NORTH: org.y--; break;
1351. 		      case W_SOUTH: org.y++; break;
1352. 		      case W_WEST:  org.x--; break;
1353. 		      case W_EAST:  org.x++; break;
1354. 		}
1355. 		switch(c->dest.wall) {
1356. 		      case W_NORTH: dest.y--; break;
1357. 		      case W_SOUTH: dest.y++; break;
1358. 		      case W_WEST:  dest.x--; break;
1359. 		      case W_EAST:  dest.x++; break;
1360. 		}
1361. 		(void) dig_corridor(&org, &dest, FALSE, CORR, STONE);
1362. 	}
1363. }
1364. 
1365. 
1366. /*
1367.  * Fill a room (shop, zoo, etc...) with appropriate stuff.
1368.  */
1369. 
1370. void
1371. fill_room(croom, prefilled)
1372. struct mkroom *croom;
1373. boolean prefilled;
1374. {
1375. 	if (!croom || croom->rtype == OROOM)
1376. 	    return;
1377. 
1378. 	if (!prefilled) {
1379. 	    int x,y;
1380. 
1381. 	    /* Shop ? */
1382. 	    if (croom->rtype >= SHOPBASE) {
1383. 		    stock_room(croom->rtype - SHOPBASE, croom);
1384. 		    level.flags.has_shop = TRUE;
1385. 		    return;
1386. 	    }
1387. 
1388. 	    switch (croom->rtype) {
1389. 		case VAULT:
1390. 		    for (x=croom->lx;x<=croom->hx;x++)
1391. 			for (y=croom->ly;y<=croom->hy;y++)
1392. 			    mkgold((long)rn1(abs(depth(&u.uz))*100, 51), x, y);
1393. 		    break;
1394. 		case COURT:
1395. 		case ZOO:
1396. 		case BEEHIVE:
1397. 		case MORGUE:
1398. 		case BARRACKS:
1399. 		    fill_zoo(croom);
1400. 		    break;
1401. 	    }
1402. 	}
1403. 	switch (croom->rtype) {
1404. 	    case VAULT:
1405. 		level.flags.has_vault = TRUE;
1406. 		break;
1407. 	    case ZOO:
1408. 		level.flags.has_zoo = TRUE;
1409. 		break;
1410. 	    case COURT:
1411. 		level.flags.has_court = TRUE;
1412. 		break;
1413. 	    case MORGUE:
1414. 		level.flags.has_morgue = TRUE;
1415. 		break;
1416. 	    case BEEHIVE:
1417. 		level.flags.has_beehive = TRUE;
1418. 		break;
1419. 	    case BARRACKS:
1420. 		level.flags.has_barracks = TRUE;
1421. 		break;
1422. 	    case TEMPLE:
1423. 		level.flags.has_temple = TRUE;
1424. 		break;
1425. 	    case SWAMP:
1426. 		level.flags.has_swamp = TRUE;
1427. 		break;
1428. 	}
1429. }
1430. 
1431. static void
1432. free_rooms(ro, n)
1433. room **ro;
1434. int n;
1435. {
1436. 	short j;
1437. 	room *r;
1438. 	
1439. 	while(n--) {
1440. 		r = ro[n];
1441. 		Free(r->name);
1442. 		Free(r->parent);
1443. 		if ((j = r->ndoor) != 0) {
1444. 			while(j--)
1445. 			    Free(r->doors[j]);
1446. 			Free(r->doors);
1447. 		}
1448. 		if ((j = r->nstair) != 0) {
1449. 			while(j--)
1450. 			    Free(r->stairs[j]);
1451. 			Free(r->stairs);
1452. 		}
1453. 		if ((j = r->naltar) != 0) {
1454. 			while (j--)
1455. 			    Free(r->altars[j]);
1456. 			Free(r->altars);
1457. 		}
1458. 		if ((j = r->nfountain) != 0) {
1459. 			while(j--)
1460. 			    Free(r->fountains[j]);
1461. 			Free(r->fountains);
1462. 		}
1463. 		if ((j = r->nsink) != 0) {
1464. 			while(j--)
1465. 			    Free(r->sinks[j]);
1466. 			Free(r->sinks);
1467. 		}
1468. 		if ((j = r->npool) != 0) {
1469. 			while(j--)
1470. 			    Free(r->pools[j]);
1471. 			Free(r->pools);
1472. 		}
1473. 		if ((j = r->ntrap) != 0) {
1474. 			while (j--)
1475. 			    Free(r->traps[j]);
1476. 			Free(r->traps);
1477. 		}
1478. 		if ((j = r->nmonster) != 0) {
1479. 			while (j--)
1480. 				Free(r->monsters[j]);
1481. 			Free(r->monsters);
1482. 		}
1483. 		if ((j = r->nobject) != 0) {
1484. 			while (j--)
1485. 				Free(r->objects[j]);
1486. 			Free(r->objects);
1487. 		}
1488. 		if ((j = r->ngold) != 0) {
1489. 			while(j--)
1490. 			    Free(r->golds[j]);
1491. 			Free(r->golds);
1492. 		}
1493. 		if ((j = r->nengraving) != 0) {
1494. 			while (j--)
1495. 				Free(r->engravings[j]);
1496. 			Free(r->engravings);
1497. 		}
1498. 		Free(r);
1499. 	}
1500. 	Free(ro);
1501. }
1502. 
1503. static void
1504. build_room(r, pr)
1505. room *r, *pr;
1506. {
1507. 	boolean okroom;
1508. 	struct mkroom	*aroom;
1509. 	short i;
1510. 	xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
1511. 
1512. 	if(pr) {
1513. 		aroom = &subrooms[nsubroom];
1514. 		okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h,
1515. 					rtype, r->rlit);
1516. 	} else {
1517. 		aroom = &rooms[nroom];
1518. 		okroom = create_room(r->x, r->y, r->w, r->h, r->xalign,
1519. 				     r->yalign, rtype, r->rlit);
1520. 		r->mkr = aroom;
1521. 	}
1522. 
1523. 	if (okroom) {
1524. 		/* Create subrooms if necessary... */
1525. 		for(i=0; i < r->nsubroom; i++)
1526. 		    build_room(r->subrooms[i], r);
1527. 		/* And now we can fill the room! */
1528. 		
1529. 		/* Priority to the stairs */
1530. 
1531. 		for(i=0; i <r->nstair; i++)
1532. 		    create_stairs(r->stairs[i], aroom);
1533. 
1534. 		/* Then to the various elements (sinks, etc..) */
1535. 		for(i = 0; i<r->nsink; i++)
1536. 		    create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK);
1537. 		for(i = 0; i<r->npool; i++)
1538. 		    create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL);
1539. 		for(i = 0; i<r->nfountain; i++)
1540. 		    create_feature(r->fountains[i]->x, r->fountains[i]->y,
1541. 				   aroom, FOUNTAIN);
1542. 		for(i = 0; i<r->naltar; i++)
1543. 		    create_altar(r->altars[i], aroom);
1544. 		for(i = 0; i<r->ndoor; i++)
1545. 		    create_door(r->doors[i], aroom);
1546. 
1547. 		/* The traps */
1548. 		for(i = 0; i<r->ntrap; i++)
1549. 		    create_trap(r->traps[i], aroom);
1550. 
1551. 		/* The monsters */
1552. 		for(i = 0; i<r->nmonster; i++)
1553. 		    create_monster(r->monsters[i], aroom);
1554. 
1555. 		/* The objects */
1556. 		for(i = 0; i<r->nobject; i++)
1557. 		    create_object(r->objects[i], aroom);
1558. 
1559. 		/* The gold piles */
1560. 		for(i = 0; i<r->ngold; i++)
1561. 		    create_gold(r->golds[i], aroom);
1562. 
1563. 		/* The engravings */
1564. 		for (i = 0; i < r->nengraving; i++)
1565. 		    create_engraving(r->engravings[i], aroom);
1566. 
1567. #ifdef SPECIALIZATION
1568. 		topologize(aroom,FALSE);		/* set roomno */
1569. #else
1570. 		topologize(aroom);			/* set roomno */
1571. #endif
1572. 		/* MRS - 07/04/91 - This is temporary but should result
1573. 		 * in proper filling of shops, etc.
1574. 		 * DLC - this can fail if corridors are added to this room
1575. 		 * at a later point.  Currently no good way to fix this.
1576. 		 */
1577. 		if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE);
1578. 	}
1579. }
1580. 
1581. /*
1582.  * set lighting in a region that will not become a room.
1583.  */
1584. static void
1585. light_region(tmpregion)
1586.     region  *tmpregion;
1587. {
1588.     register boolean litstate = tmpregion->rlit ? 1 : 0;
1589.     register int hiy = tmpregion->y2;
1590.     register int x, y;
1591.     register struct rm *lev;
1592.     int lowy = tmpregion->y1;
1593.     int lowx = tmpregion->x1, hix = tmpregion->x2;
1594. 
1595.     if(litstate) {
1596. 	/* adjust region size for walls, but only if lighted */
1597. 	lowx = max(lowx-1,1);
1598. 	hix = min(hix+1,COLNO-1);
1599. 	lowy = max(lowy-1,0);
1600. 	hiy = min(hiy+1, ROWNO-1);
1601.     }
1602.     for(x = lowx; x <= hix; x++) {
1603. 	lev = &levl[x][lowy];
1604. 	for(y = lowy; y <= hiy; y++)
1605. 	    lev++->lit = litstate;
1606.     }
1607. }
1608. 
1609. /* initialization common to all special levels */
1610. static void
1611. load_common_data(fd, typ)
1612. dlb *fd;
1613. int typ;
1614. {
1615. 	uchar	n;
1616. 	long	lev_flags;
1617. 	int	i;
1618. 
1619.       {
1620. 	aligntyp atmp;
1621. 	/* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */
1622. 	i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
1623. 	if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
1624.       }
1625. 
1626. 	level.flags.is_maze_lev = typ == SP_LEV_MAZE;
1627. 
1628. 	/* Read the level initialization data */
1629. 	Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd);
1630. 	if(init_lev.init_present) {
1631. 	    if(init_lev.lit < 0)
1632. 		init_lev.lit = rn2(2);
1633. 	    mkmap(&init_lev);
1634. 	}
1635. 
1636. 	/* Read the per level flags */
1637. 	Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd);
1638. 	if (lev_flags & NOTELEPORT)
1639. 	    level.flags.noteleport = 1;
1640. 	if (lev_flags & HARDFLOOR)
1641. 	    level.flags.hardfloor = 1;
1642. 	if (lev_flags & NOMMAP)
1643. 	    level.flags.nommap = 1;
1644. 	if (lev_flags & SHORTSIGHTED)
1645. 	    level.flags.shortsighted = 1;
1646. 
1647. 	/* Read message */
1648. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
1649. 	if (n) {
1650. 	    lev_message = (char *) alloc(n + 1);
1651. 	    Fread((genericptr_t) lev_message, 1, (int) n, fd);
1652. 	    lev_message[n] = 0;
1653. 	}
1654. }
1655. 
1656. static void
1657. load_one_monster(fd, m)
1658. dlb *fd;
1659. monster *m;
1660. {
1661. 	int size;
1662. 
1663. 	Fread((genericptr_t) m, 1, sizeof *m, fd);
1664. 	if ((size = m->name.len) != 0) {
1665. 	    m->name.str = (char *) alloc((unsigned)size + 1);
1666. 	    Fread((genericptr_t) m->name.str, 1, size, fd);
1667. 	    m->name.str[size] = '\0';
1668. 	} else
1669. 	    m->name.str = (char *) 0;
1670. 	if ((size = m->appear_as.len) != 0) {
1671. 	    m->appear_as.str = (char *) alloc((unsigned)size + 1);
1672. 	    Fread((genericptr_t) m->appear_as.str, 1, size, fd);
1673. 	    m->appear_as.str[size] = '\0';
1674. 	} else
1675. 	    m->appear_as.str = (char *) 0;
1676. }
1677. 
1678. static void
1679. load_one_object(fd, o)
1680. dlb *fd;
1681. object *o;
1682. {
1683. 	int size;
1684. 
1685. 	Fread((genericptr_t) o, 1, sizeof *o, fd);
1686. 	if ((size = o->name.len) != 0) {
1687. 	    o->name.str = (char *) alloc((unsigned)size + 1);
1688. 	    Fread((genericptr_t) o->name.str, 1, size, fd);
1689. 	    o->name.str[size] = '\0';
1690. 	} else
1691. 	    o->name.str = (char *) 0;
1692. }
1693. 
1694. static void
1695. load_one_engraving(fd, e)
1696. dlb *fd;
1697. engraving *e;
1698. {
1699. 	int size;
1700. 
1701. 	Fread((genericptr_t) e, 1, sizeof *e, fd);
1702. 	size = e->engr.len;
1703. 	e->engr.str = (char *) alloc((unsigned)size+1);
1704. 	Fread((genericptr_t) e->engr.str, 1, size, fd);
1705. 	e->engr.str[size] = '\0';
1706. }
1707. 
1708. static boolean
1709. load_rooms(fd)
1710. dlb *fd;
1711. {
1712. 	xchar		nrooms, ncorr;
1713. 	char		n;
1714. 	short		size;
1715. 	corridor	tmpcor;
1716. 	room**		tmproom;
1717. 	int		i, j;
1718. 
1719. 	load_common_data(fd, SP_LEV_ROOMS);
1720. 
1721. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */
1722. 	if (n) {
1723. 		Fread((genericptr_t)robjects, sizeof(*robjects), n, fd);
1724. 		sp_lev_shuffle(robjects, (char *)0, (int)n);
1725. 	}
1726. 
1727. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */
1728. 	if (n) {
1729. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd);
1730. 		sp_lev_shuffle(rmonst, (char *)0, (int)n);
1731. 	}
1732. 
1733. 	Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd);
1734. 						/* Number of rooms to read */
1735. 	tmproom = NewTab(room,nrooms);
1736. 	for (i=0;i<nrooms;i++) {
1737. 		room *r;
1738. 
1739. 		r = tmproom[i] = New(room);
1740. 
1741. 		/* Let's see if this room has a name */
1742. 		Fread((genericptr_t) &size, 1, sizeof(size), fd);
1743. 		if (size > 0) {	/* Yup, it does! */
1744. 			r->name = (char *) alloc((unsigned)size + 1);
1745. 			Fread((genericptr_t) r->name, 1, size, fd);
1746. 			r->name[size] = 0;
1747. 		} else
1748. 		    r->name = (char *) 0;
1749. 
1750. 		/* Let's see if this room has a parent */
1751. 		Fread((genericptr_t) &size, 1, sizeof(size), fd);
1752. 		if (size > 0) {	/* Yup, it does! */
1753. 			r->parent = (char *) alloc((unsigned)size + 1);
1754. 			Fread((genericptr_t) r->parent, 1, size, fd);
1755. 			r->parent[size] = 0;
1756. 		} else
1757. 		    r->parent = (char *) 0;
1758. 		
1759. 		Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd);
1760. 					/* x pos on the grid (1-5) */
1761. 		Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd);
1762. 					 /* y pos on the grid (1-5) */
1763. 		Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd);
1764. 					 /* width of the room */
1765. 		Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd);
1766. 					 /* height of the room */
1767. 		Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd);
1768. 					 /* horizontal alignment */
1769. 		Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd);
1770. 					 /* vertical alignment */
1771. 		Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd);
1772. 					 /* type of room (zoo, shop, etc.) */
1773. 		Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd);
1774. 					 /* chance of room being special. */
1775. 		Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd);
1776. 					 /* lit or not ? */
1777. 		Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd);
1778. 					 /* to be filled? */
1779. 		r->nsubroom= 0;
1780. 
1781. 		/* read the doors */
1782. 		Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd);
1783. 		if ((n = r->ndoor) != 0)
1784. 		    r->doors = NewTab(room_door, n);
1785. 		while(n--) {
1786. 			r->doors[n] = New(room_door);
1787. 			Fread((genericptr_t) r->doors[n], 1,
1788. 				sizeof(room_door), fd);
1789. 		}
1790. 
1791. 		/* read the stairs */
1792. 		Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd);
1793. 		if ((n = r->nstair) != 0)
1794. 		    r->stairs = NewTab(stair, n);
1795. 		while (n--) {
1796. 			r->stairs[n] = New(stair);
1797. 			Fread((genericptr_t) r->stairs[n], 1,
1798. 				sizeof(stair), fd);
1799. 		}
1800. 
1801. 		/* read the altars */
1802. 		Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd);
1803. 		if ((n = r->naltar) != 0)
1804. 		    r->altars = NewTab(altar, n);
1805. 		while (n--) {
1806. 			r->altars[n] = New(altar);
1807. 			Fread((genericptr_t) r->altars[n], 1,
1808. 				sizeof(altar), fd);
1809. 		}
1810. 
1811. 		/* read the fountains */
1812. 		Fread((genericptr_t) &r->nfountain, 1,
1813. 			sizeof(r->nfountain), fd);
1814. 		if ((n = r->nfountain) != 0)
1815. 		    r->fountains = NewTab(fountain, n);
1816. 		while (n--) {
1817. 			r->fountains[n] = New(fountain);
1818. 			Fread((genericptr_t) r->fountains[n], 1,
1819. 				sizeof(fountain), fd);
1820. 		}
1821. 
1822. 		/* read the sinks */
1823. 		Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd);
1824. 		if ((n = r->nsink) != 0)
1825. 		    r->sinks = NewTab(sink, n);
1826. 		while (n--) {
1827. 			r->sinks[n] = New(sink);
1828. 			Fread((genericptr_t) r->sinks[n], 1, sizeof(sink), fd);
1829. 		}
1830. 
1831. 		/* read the pools */
1832. 		Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd);
1833. 		if ((n = r->npool) != 0)
1834. 		    r->pools = NewTab(pool,n);
1835. 		while (n--) {
1836. 			r->pools[n] = New(pool);
1837. 			Fread((genericptr_t) r->pools[n], 1, sizeof(pool), fd);
1838. 		}
1839. 
1840. 		/* read the traps */
1841. 		Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd);
1842. 		if ((n = r->ntrap) != 0)
1843. 		    r->traps = NewTab(trap, n);
1844. 		while(n--) {
1845. 			r->traps[n] = New(trap);
1846. 			Fread((genericptr_t) r->traps[n], 1, sizeof(trap), fd);
1847. 		}
1848. 
1849. 		/* read the monsters */
1850. 		Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd);
1851. 		if ((n = r->nmonster) != 0) {
1852. 		    r->monsters = NewTab(monster, n);
1853. 		    while(n--) {
1854. 			r->monsters[n] = New(monster);
1855. 			load_one_monster(fd, r->monsters[n]);
1856. 		    }
1857. 		} else
1858. 		    r->monsters = 0;
1859. 
1860. 		/* read the objects */
1861. 		Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd);
1862. 		if ((n = r->nobject) != 0) {
1863. 		    r->objects = NewTab(object, n);
1864. 		    while (n--) {
1865. 			r->objects[n] = New(object);
1866. 			load_one_object(fd, r->objects[n]);
1867. 		    }
1868. 		} else
1869. 		    r->objects = 0;
1870. 
1871. 		/* read the gold piles */
1872. 		Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd);
1873. 		if ((n = r->ngold) != 0)
1874. 		    r->golds = NewTab(gold, n);
1875. 		while (n--) {
1876. 			r->golds[n] = New(gold);
1877. 			Fread((genericptr_t) r->golds[n], 1, sizeof(gold), fd);
1878. 		}
1879. 
1880. 		/* read the engravings */
1881. 		Fread((genericptr_t) &r->nengraving, 1,
1882. 			sizeof(r->nengraving), fd);
1883. 		if ((n = r->nengraving) != 0) {
1884. 		    r->engravings = NewTab(engraving,n);
1885. 		    while (n--) {
1886. 			r->engravings[n] = New(engraving);
1887. 			load_one_engraving(fd, r->engravings[n]);
1888. 		    }
1889. 		} else
1890. 		    r->engravings = 0;
1891. 
1892. 	}
1893. 
1894. 	/* Now that we have loaded all the rooms, search the
1895. 	 * subrooms and create the links.
1896. 	 */
1897. 
1898. 	for (i = 0; i<nrooms; i++)
1899. 	    if (tmproom[i]->parent) {
1900. 		    /* Search the parent room */
1901. 		    for(j=0; j<nrooms; j++)
1902. 			if (tmproom[j]->name && !strcmp(tmproom[j]->name,
1903. 						       tmproom[i]->parent)) {
1904. 				n = tmproom[j]->nsubroom++;
1905. 				tmproom[j]->subrooms[(int)n] = tmproom[i];
1906. 				break;
1907. 			}
1908. 	    }
1909. 
1910. 	/*
1911. 	 * Create the rooms now...
1912. 	 */
1913. 
1914. 	for (i=0; i < nrooms; i++)
1915. 	    if(!tmproom[i]->parent)
1916. 		build_room(tmproom[i], (room *) 0);
1917. 
1918. 	free_rooms(tmproom, nrooms);
1919. 
1920. 	/* read the corridors */
1921. 
1922. 	Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd);
1923. 	for (i=0; i<ncorr; i++) {
1924. 		Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd);
1925. 		create_corridor(&tmpcor);
1926. 	}
1927. 
1928. 	return TRUE;
1929. }
1930. 
1931. /*
1932.  * Select a random coordinate in the maze.
1933.  *
1934.  * We want a place not 'touched' by the loader.  That is, a place in
1935.  * the maze outside every part of the special level.
1936.  */
1937. 
1938. static void
1939. maze1xy(m, humidity)
1940. coord *m;
1941. int humidity;
1942. {
1943. 	register int x, y, tryct = 2000;
1944. 	/* tryct:  normally it won't take more than ten or so tries due
1945. 	   to the circumstances under which we'll be called, but the
1946. 	   `humidity' screening might drastically change the chances */
1947. 
1948. 	do {
1949. 	    x = rn1(x_maze_max - 3, 3);
1950. 	    y = rn1(y_maze_max - 3, 3);
1951. 	    if (--tryct < 0) break;	/* give up */
1952. 	} while (!(x % 2) || !(y % 2) || Map[x][y] ||
1953. 		 !is_ok_location((schar)x, (schar)y, humidity));
1954. 
1955. 	m->x = (xchar)x,  m->y = (xchar)y;
1956. }
1957. 
1958. /*
1959.  * The Big Thing: special maze loader
1960.  *
1961.  * Could be cleaner, but it works.
1962.  */
1963. 
1964. static boolean
1965. load_maze(fd)
1966. dlb *fd;
1967. {
1968.     xchar   x, y, typ;
1969.     boolean prefilled, room_not_needed;
1970. 
1971.     char    n, numpart = 0;
1972.     xchar   nwalk = 0, nwalk_sav;
1973.     short   filling;
1974.     char    halign, valign;
1975. 
1976.     int     xi, dir, size;
1977.     coord   mm;
1978.     int     mapcount, mapcountmax, mapfact;
1979. 
1980.     lev_region  tmplregion;
1981.     region  tmpregion;
1982.     door    tmpdoor;
1983.     trap    tmptrap;
1984.     monster tmpmons;
1985.     object  tmpobj;
1986.     drawbridge tmpdb;
1987.     walk    tmpwalk;
1988.     digpos  tmpdig;
1989.     lad     tmplad;
1990.     stair   tmpstair, prevstair;
1991.     altar   tmpaltar;
1992.     gold    tmpgold;
1993.     fountain tmpfountain;
1994.     engraving tmpengraving;
1995.     xchar   mustfill[(MAXNROFROOMS+1)*2];
1996.     struct trap *badtrap;
1997.     boolean has_bounds;
1998. 
1999.     (void) memset((genericptr_t)&Map[0][0], 0, sizeof Map);
2000.     load_common_data(fd, SP_LEV_MAZE);
2001. 
2002.     /* Initialize map */
2003.     Fread((genericptr_t) &filling, 1, sizeof(filling), fd);
2004.     if(!init_lev.init_present) /* don't init if mkmap() has been called */
2005.       for(x = 2; x <= x_maze_max; x++)
2006. 	for(y = 0; y <= y_maze_max; y++)
2007. 	    if (filling == -1) {
2008. #ifndef WALLIFIED_MAZE
2009. 		    levl[x][y].typ = STONE;
2010. #else
2011. 		    levl[x][y].typ =
2012. 			(y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL;
2013. #endif
2014. 	    } else {
2015. 		    levl[x][y].typ = filling;
2016. 	    }
2017. 
2018.     /* Start reading the file */
2019.     Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
2020. 						/* Number of parts */
2021.     if (!numpart || numpart > 9)
2022. 	panic("load_maze error: numpart = %d", (int) numpart);
2023. 
2024.     while (numpart--) {
2025. 	Fread((genericptr_t) &halign, 1, sizeof(halign), fd);
2026. 					/* Horizontal alignment */
2027. 	Fread((genericptr_t) &valign, 1, sizeof(valign), fd);
2028. 					/* Vertical alignment */
2029. 	Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd);
2030. 					/* size in X */
2031. 	Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd);
2032. 					/* size in Y */
2033. 	switch((int) halign) {
2034. 	    case LEFT:	    xstart = 3;					break;
2035. 	    case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);	break;
2036. 	    case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break;
2037. 	    case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);	break;
2038. 	    case RIGHT:     xstart = x_maze_max-xsize-1;		break;
2039. 	}
2040. 	switch((int) valign) {
2041. 	    case TOP:	    ystart = 3;					break;
2042. 	    case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break;
2043. 	    case BOTTOM:    ystart = y_maze_max-ysize-1;		break;
2044. 	}
2045. 	if (!(xstart % 2)) xstart++;
2046. 	if (!(ystart % 2)) ystart++;
2047. 	if ((ystart < 0) || (ystart + ysize > ROWNO)) {
2048. 	    /* try to move the start a bit */
2049. 	    ystart += (ystart > 0) ? -2 : 2;
2050. 	    if(ysize == ROWNO) ystart = 0;
2051. 	    if(ystart < 0 || ystart + ysize > ROWNO)
2052. 		panic("reading special level with ysize too large");
2053. 	}
2054. 
2055. 	/*
2056. 	 * If any CROSSWALLs are found, must change to ROOM after REGION's
2057. 	 * are laid out.  CROSSWALLS are used to specify "invisible"
2058. 	 * boundaries where DOOR syms look bad or aren't desirable.
2059. 	 */
2060. 	has_bounds = FALSE;
2061. 
2062. 	if(init_lev.init_present && xsize <= 1 && ysize <= 1) {
2063. 	    xstart = 1;
2064. 	    ystart = 0;
2065. 	    xsize = COLNO-1;
2066. 	    ysize = ROWNO;
2067. 	} else {
2068. 	    /* Load the map */
2069. 	    for(y = ystart; y < ystart+ysize; y++)
2070. 		for(x = xstart; x < xstart+xsize; x++) {
2071. 		    levl[x][y].typ = Fgetc(fd);
2072. 		    levl[x][y].lit = FALSE;
2073. 		    /*
2074. 		     * Note: Even though levl[x][y].typ is type schar,
2075. 		     *	 lev_comp.y saves it as type char. Since schar != char
2076. 		     *	 all the time we must make this exception or hack
2077. 		     *	 through lev_comp.y to fix.
2078. 		     */
2079. 
2080. 		    /*
2081. 		     *  Set secret doors to closed (why not trapped too?).  Set
2082. 		     *  the horizontal bit.
2083. 		     */
2084. 		    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
2085. 			if(levl[x][y].typ == SDOOR)
2086. 			    levl[x][y].doormask = D_CLOSED;
2087. 			/*
2088. 			 *  If there is a wall to the left that connects to a
2089. 			 *  (secret) door, then it is horizontal.  This does
2090. 			 *  not allow (secret) doors to be corners of rooms.
2091. 			 */
2092. 			if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
2093. 					    levl[x-1][y].horizontal))
2094. 			    levl[x][y].horizontal = 1;
2095. 		    } else if(levl[x][y].typ == HWALL)
2096. 			levl[x][y].horizontal = 1;
2097. 		    else if(levl[x][y].typ == LAVAPOOL)
2098. 			levl[x][y].lit = 1;
2099. 		    else if(levl[x][y].typ == CROSSWALL)
2100. 			has_bounds = TRUE;
2101. 		    Map[x][y] = 1;
2102. 		}
2103. 	}
2104. 
2105. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2106. 						/* Number of level regions */
2107. 	if(n) {
2108. 	    if(num_lregions) {
2109. 		/* realloc the lregion space to add the new ones */
2110. 		/* don't really free it up until the whole level is done */
2111. 		lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
2112. 						(unsigned)(n+num_lregions));
2113. 		(void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions,
2114. 					sizeof(lev_region) * num_lregions);
2115. 		Free(lregions);
2116. 		num_lregions += n;
2117. 		lregions = newl;
2118. 	    } else {
2119. 		num_lregions = n;
2120. 		lregions = (lev_region *)
2121. 				alloc(sizeof(lev_region) * (unsigned)n);
2122. 	    }
2123. 	}
2124. 
2125. 	while(n--) {
2126. 	    Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd);
2127. 	    if ((size = tmplregion.rname.len) != 0) {
2128. 		tmplregion.rname.str = (char *) alloc((unsigned)size + 1);
2129. 		Fread((genericptr_t) tmplregion.rname.str, size, 1, fd);
2130. 		tmplregion.rname.str[size] = '\0';
2131. 	    } else
2132. 		tmplregion.rname.str = (char *) 0;
2133. 	    if(!tmplregion.in_islev) {
2134. 		get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1,
2135. 								DRY|WET);
2136. 		get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2,
2137. 								DRY|WET);
2138. 	    }
2139. 	    if(!tmplregion.del_islev) {
2140. 		get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1,
2141. 								DRY|WET);
2142. 		get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2,
2143. 								DRY|WET);
2144. 	    }
2145. 	    lregions[n] = tmplregion;
2146. 	}
2147. 
2148. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2149. 						/* Random objects */
2150. 	if(n) {
2151. 		Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd);
2152. 		sp_lev_shuffle(robjects, (char *)0, (int)n);
2153. 	}
2154. 
2155. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2156. 						/* Random locations */
2157. 	if(n) {
2158. 		Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd);
2159. 		Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd);
2160. 		sp_lev_shuffle(rloc_x, rloc_y, (int)n);
2161. 	}
2162. 
2163. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2164. 						/* Random monsters */
2165. 	if(n) {
2166. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd);
2167. 		sp_lev_shuffle(rmonst, (char *)0, (int)n);
2168. 	}
2169. 
2170. 	(void) memset((genericptr_t)mustfill, 0, sizeof(mustfill));
2171. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2172. 						/* Number of subrooms */
2173. 	while(n--) {
2174. 		register struct mkroom *troom;
2175. 
2176. 		Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd);
2177. 
2178. 		if(tmpregion.rtype > MAXRTYPE) {
2179. 		    tmpregion.rtype -= MAXRTYPE+1;
2180. 		    prefilled = TRUE;
2181. 		} else
2182. 		    prefilled = FALSE;
2183. 
2184. 		if(tmpregion.rlit < 0)
2185. 		    tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
2186. 			? TRUE : FALSE;
2187. 
2188. 		get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET);
2189. 		get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET);
2190. 
2191. 		/* for an ordinary room, `prefilled' is a flag to force
2192. 		   an actual room to be created (such rooms are used to
2193. 		   control placement of migrating monster arrivals) */
2194. 		room_not_needed = (tmpregion.rtype == OROOM &&
2195. 				   !tmpregion.rirreg && !prefilled);
2196. 		if (room_not_needed || nroom >= MAXNROFROOMS) {
2197. 		    if (!room_not_needed)
2198. 			impossible("Too many rooms on new level!");
2199. 		    light_region(&tmpregion);
2200. 		    continue;
2201. 		}
2202. 
2203. 		troom = &rooms[nroom];
2204. 
2205. 		/* mark rooms that must be filled, but do it later */
2206. 		if (tmpregion.rtype != OROOM)
2207. 		    mustfill[nroom] = (prefilled ? 2 : 1);
2208. 
2209. 		if(tmpregion.rirreg) {
2210. 		    min_rx = max_rx = tmpregion.x1;
2211. 		    min_ry = max_ry = tmpregion.y1;
2212. 		    flood_fill_rm(tmpregion.x1, tmpregion.y1,
2213. 				  nroom+ROOMOFFSET, tmpregion.rlit, TRUE);
2214. 		    add_room(min_rx, min_ry, max_rx, max_ry,
2215. 			     FALSE, tmpregion.rtype, TRUE);
2216. 		    troom->rlit = tmpregion.rlit;
2217. 		    troom->irregular = TRUE;
2218. 		} else {
2219. 		    add_room(tmpregion.x1, tmpregion.y1,
2220. 			     tmpregion.x2, tmpregion.y2,
2221. 			     tmpregion.rlit, tmpregion.rtype, TRUE);
2222. #ifdef SPECIALIZATION
2223. 		    topologize(troom,FALSE);		/* set roomno */
2224. #else
2225. 		    topologize(troom);			/* set roomno */
2226. #endif
2227. 		}
2228. 	}
2229. 
2230. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2231. 						/* Number of doors */
2232. 	while(n--) {
2233. 		struct mkroom *croom = &rooms[0];
2234. 
2235. 		Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd);
2236. 
2237. 		x = tmpdoor.x;	y = tmpdoor.y;
2238. 		typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
2239. 
2240. 		get_location(&x, &y, DRY);
2241. 		if(levl[x][y].typ != SDOOR)
2242. 			levl[x][y].typ = DOOR;
2243. 		else {
2244. 			if(typ < D_CLOSED)
2245. 			    typ = D_CLOSED; /* force it to be closed */
2246. 		}
2247. 		levl[x][y].doormask = typ;
2248. 
2249. 		/* Now the complicated part, list it with each subroom */
2250. 		/* The dog move and mail daemon routines use this */
2251. 		while(croom->hx >= 0 && doorindex < DOORMAX) {
2252. 		    if(croom->hx >= x-1 && croom->lx <= x+1 &&
2253. 		       croom->hy >= y-1 && croom->ly <= y+1) {
2254. 			/* Found it */
2255. 			add_door(x, y, croom);
2256. 		    }
2257. 		    croom++;
2258. 		}
2259. 	}
2260. 
2261. 	/* now that we have rooms _and_ associated doors, fill the rooms */
2262. 	for(n = 0; n < SIZE(mustfill); n++)
2263. 	    if(mustfill[(int)n])
2264. 		fill_room(&rooms[(int)n], (mustfill[(int)n] == 2));
2265. 
2266. 	/* if special boundary syms (CROSSWALL) in map, remove them now */
2267. 	if(has_bounds) {
2268. 	    for(x = xstart; x < xstart+xsize; x++)
2269. 		for(y = ystart; y < ystart+ysize; y++)
2270. 		    if(levl[x][y].typ == CROSSWALL)
2271. 			levl[x][y].typ = ROOM;
2272. 	}
2273. 
2274. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2275. 						/* Number of drawbridges */
2276. 	while(n--) {
2277. 		Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd);
2278. 
2279. 		x = tmpdb.x;  y = tmpdb.y;
2280. 		get_location(&x, &y, DRY|WET);
2281. 
2282. 		if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open))
2283. 		    impossible("Cannot create drawbridge.");
2284. 	}
2285. 
2286. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2287. 						/* Number of mazewalks */
2288. 	while(n--) {
2289. 		Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd);
2290. 
2291. 		get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET);
2292. 
2293. 		walklist[nwalk++] = tmpwalk;
2294. 	}
2295. 
2296. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2297. 						/* Number of non_diggables */
2298. 	while(n--) {
2299. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
2300. 
2301. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
2302. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
2303. 
2304. 		set_wall_property(tmpdig.x1, tmpdig.y1,
2305. 				  tmpdig.x2, tmpdig.y2, W_NONDIGGABLE);
2306. 	}
2307. 
2308. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2309. 						/* Number of non_passables */
2310. 	while(n--) {
2311. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
2312. 
2313. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
2314. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
2315. 
2316. 		set_wall_property(tmpdig.x1, tmpdig.y1,
2317. 				  tmpdig.x2, tmpdig.y2, W_NONPASSWALL);
2318. 	}
2319. 
2320. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2321. 						/* Number of ladders */
2322. 	while(n--) {
2323. 		Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd);
2324. 
2325. 		x = tmplad.x;  y = tmplad.y;
2326. 		get_location(&x, &y, DRY);
2327. 
2328. 		levl[x][y].typ = LADDER;
2329. 		if (tmplad.up == 1) {
2330. 			xupladder = x;	yupladder = y;
2331. 			levl[x][y].ladder = LA_UP;
2332. 		} else {
2333. 			xdnladder = x;	ydnladder = y;
2334. 			levl[x][y].ladder = LA_DOWN;
2335. 		}
2336. 	}
2337. 
2338. 	prevstair.x = prevstair.y = 0;
2339. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2340. 						/* Number of stairs */
2341. 	while(n--) {
2342. 		Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd);
2343. 
2344. 		xi = 0;
2345. 		do {
2346. 		    x = tmpstair.x;  y = tmpstair.y;
2347. 		    get_location(&x, &y, DRY);
2348. 		} while(prevstair.x && xi++ < 100 &&
2349. 			distmin(x,y,prevstair.x,prevstair.y) <= 8);
2350. 		if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
2351. 		mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0);
2352. 		prevstair.x = x;
2353. 		prevstair.y = y;
2354. 	}
2355. 
2356. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2357. 						/* Number of altars */
2358. 	while(n--) {
2359. 		Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd);
2360. 
2361. 		create_altar(&tmpaltar, (struct mkroom *)0);
2362. 	}
2363. 
2364. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2365. 						/* Number of fountains */
2366. 	while (n--) {
2367. 		Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd);
2368. 
2369. 		create_feature(tmpfountain.x, tmpfountain.y,
2370. 			       (struct mkroom *)0, FOUNTAIN);
2371. 	}
2372. 
2373. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2374. 						/* Number of traps */
2375. 	while(n--) {
2376. 		Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd);
2377. 
2378. 		create_trap(&tmptrap, (struct mkroom *)0);
2379. 	}
2380. 
2381. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2382. 						/* Number of monsters */
2383. 	while(n--) {
2384. 		load_one_monster(fd, &tmpmons);
2385. 
2386. 		create_monster(&tmpmons, (struct mkroom *)0);
2387. 	}
2388. 
2389. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2390. 						/* Number of objects */
2391. 	while(n--) {
2392. 		load_one_object(fd, &tmpobj);
2393. 
2394. 		create_object(&tmpobj, (struct mkroom *)0);
2395. 	}
2396. 
2397. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2398. 						/* Number of gold piles */
2399. 	while (n--) {
2400. 		Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd);
2401. 
2402. 		create_gold(&tmpgold, (struct mkroom *)0);
2403. 	}
2404. 
2405. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2406. 						/* Number of engravings */
2407. 	while(n--) {
2408. 		load_one_engraving(fd, &tmpengraving);
2409. 
2410. 		create_engraving(&tmpengraving, (struct mkroom *)0);
2411. 	}
2412. 
2413.     }		/* numpart loop */
2414. 
2415.     nwalk_sav = nwalk;
2416.     while(nwalk--) {
2417. 	    x = (xchar) walklist[nwalk].x;
2418. 	    y = (xchar) walklist[nwalk].y;
2419. 	    dir = walklist[nwalk].dir;
2420. 
2421. 	    /* don't use move() - it doesn't use W_NORTH, etc. */
2422. 	    switch (dir) {
2423. 		case W_NORTH: --y; break;
2424. 		case W_SOUTH: y++; break;
2425. 		case W_EAST:  x++; break;
2426. 		case W_WEST:  --x; break;
2427. 		default: panic("load_maze: bad MAZEWALK direction");
2428. 	    }
2429. 
2430. 	    if(!IS_DOOR(levl[x][y].typ)) {
2431. #ifndef WALLIFIED_MAZE
2432. 		levl[x][y].typ = CORR;
2433. #else
2434. 		levl[x][y].typ = ROOM;
2435. #endif
2436. 		levl[x][y].flags = 0;
2437. 	    }
2438. 
2439. 	    /*
2440. 	     * We must be sure that the parity of the coordinates for
2441. 	     * walkfrom() is odd.  But we must also take into account
2442. 	     * what direction was chosen.
2443. 	     */
2444. 	    if(!(x % 2)) {
2445. 		if (dir == W_EAST)
2446. 		    x++;
2447. 		else
2448. 		    x--;
2449. 
2450. 		/* no need for IS_DOOR check; out of map bounds */
2451. #ifndef WALLIFIED_MAZE
2452. 		levl[x][y].typ = CORR;
2453. #else
2454. 		levl[x][y].typ = ROOM;
2455. #endif
2456. 		levl[x][y].flags = 0;
2457. 	    }
2458. 
2459. 	    if (!(y % 2))
2460. 		if (dir == W_SOUTH)
2461. 		    y++;
2462. 		else
2463. 		    y--;
2464. 
2465. 	    walkfrom(x, y);
2466.     }
2467.     wallification(1, 0, COLNO-1, ROWNO-1);
2468. 
2469.     /*
2470.      * If there's a significant portion of maze unused by the special level,
2471.      * we don't want it empty.
2472.      *
2473.      * Makes the number of traps, monsters, etc. proportional
2474.      * to the size of the maze.
2475.      */
2476.     mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
2477. 
2478.     for(x = 2; x < x_maze_max; x++)
2479. 	for(y = 0; y < y_maze_max; y++)
2480. 	    if(Map[x][y]) mapcount--;
2481. 
2482.     if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) {
2483. 	    mapfact = (int) ((mapcount * 100L) / mapcountmax);
2484. 	    for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
2485. 		    maze1xy(&mm, DRY);
2486. 		    (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
2487. 							mm.x, mm.y, TRUE);
2488. 	    }
2489. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
2490. 		    maze1xy(&mm, DRY);
2491. 		    (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE);
2492. 	    }
2493. 	    for (x = rn2(2); x; x--) {
2494. 		maze1xy(&mm, DRY);
2495. 		(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
2496. 	    }
2497. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
2498. 		    maze1xy(&mm, WET|DRY);
2499. 		    (void) makemon((struct permonst *) 0, mm.x, mm.y);
2500. 	    }
2501. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
2502. 		    maze1xy(&mm, DRY);
2503. 		    mkgold(0L,mm.x,mm.y);
2504. 	    }
2505. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
2506. 		    int trytrap;
2507. 
2508. 		    maze1xy(&mm, DRY);
2509. 		    trytrap = rndtrap();
2510. 		    if (sobj_at(BOULDER, mm.x, mm.y))
2511. 			while (trytrap == PIT || trytrap == SPIKED_PIT ||
2512. 				trytrap == TRAPDOOR || trytrap == HOLE)
2513. 			    trytrap = rndtrap();
2514. 		    (void) maketrap(mm.x, mm.y, trytrap);
2515. 	    }
2516.     }
2517.     return TRUE;
2518. }
2519. 
2520. /*
2521.  * General loader
2522.  */
2523. 
2524. boolean
2525. load_special(name)
2526. const char *name;
2527. {
2528. 	dlb *fd;
2529. 	boolean result = FALSE;
2530. 	char c;
2531. 	long vers_info[3];
2532. 
2533. 	fd = dlb_fopen(name, RDBMODE);
2534. 	if (!fd) return FALSE;
2535. 
2536. 	Fread((genericptr_t) vers_info, sizeof vers_info, 1, fd);
2537. 	if (!check_version(vers_info, name, TRUE))
2538. 	    goto give_up;
2539. 
2540. 	Fread((genericptr_t) &c, sizeof c, 1, fd); /* c Header */
2541. 
2542. 	switch (c) {
2543. 		case SP_LEV_ROOMS:
2544. 		    result = load_rooms(fd);
2545. 		    break;
2546. 		case SP_LEV_MAZE:
2547. 		    result = load_maze(fd);
2548. 		    break;
2549. 		default:	/* ??? */
2550. 		    result = FALSE;
2551. 	}
2552.  give_up:
2553. 	(void)dlb_fclose(fd);
2554. 	return result;
2555. }
2556. 
2557. /*sp_lev.c*/

Also on Fandom

Random Wiki