Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/sp lev.c

2,035pages on
this wiki
Add New Page
Talk0

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

The latest source code for vanilla NetHack is at Source code.


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

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.