Wikia

Wikihack

Source:Sp lev.c

2,032pages on
this wiki
Talk0

Below is the full text to src/sp_lev.c from NetHack 3.4.3. To link to a particular line, write [[sp_lev.c#line123]], for example.

Top of file Edit

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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], rloc_y[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.   
77.   STATIC_DCL void FDECL(set_wall_property, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,int));
78.   STATIC_DCL int NDECL(rnddoor);
79.   STATIC_DCL int NDECL(rndtrap);
80.   STATIC_DCL void FDECL(get_location, (schar *,schar *,int));
81.   STATIC_DCL void FDECL(sp_lev_shuffle, (char *,char *,int));
82.   STATIC_DCL void FDECL(light_region, (region *));
83.   STATIC_DCL void FDECL(load_common_data, (dlb *,int));
84.   STATIC_DCL void FDECL(load_one_monster, (dlb *,monster *));
85.   STATIC_DCL void FDECL(load_one_object, (dlb *,object *));
86.   STATIC_DCL void FDECL(load_one_engraving, (dlb *,engraving *));
87.   STATIC_DCL boolean FDECL(load_rooms, (dlb *));
88.   STATIC_DCL void FDECL(maze1xy, (coord *,int));
89.   STATIC_DCL boolean FDECL(load_maze, (dlb *));
90.   STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
91.   STATIC_DCL void FDECL(free_rooms,(room **, int));
92.   STATIC_DCL void FDECL(build_room, (room *, room*));
93.   
94.   char *lev_message = 0;
95.   lev_region *lregions = 0;
96.   int num_lregions = 0;
97.   lev_init init_lev;
98.   

set_wall_property Edit

99.   /*
100.   * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able
101.   */
102.  
103.  STATIC_OVL void
104.  set_wall_property(x1,y1,x2,y2, prop)
105.  xchar x1, y1, x2, y2;
106.  int prop;
107.  {
108.  	register xchar x, y;
109.  
110.  	for(y = y1; y <= y2; y++)
111.  	    for(x = x1; x <= x2; x++)
112.  		if(IS_STWALL(levl[x][y].typ))
113.  		    levl[x][y].wall_info |= prop;
114.  }
115.  

rnddoor Edit

116.  /*
117.   * Choose randomly the state (nodoor, open, closed or locked) for a door
118.   */
119.  STATIC_OVL int
120.  rnddoor()
121.  {
122.  	int i = 1 << rn2(5);
123.  	i >>= 1;
124.  	return i;
125.  }
126.  

rndtrap Edit

127.  /*
128.   * Select a random trap
129.   */
130.  STATIC_OVL int
131.  rndtrap()
132.  {
133.  	int rtrap;
134.  
135.  	do {
136.  	    rtrap = rnd(TRAPNUM-1);
137.  	    switch (rtrap) {
138.  	     case HOLE:		/* no random holes on special levels */
139.  	     case MAGIC_PORTAL:	rtrap = NO_TRAP;
140.  				break;
141.  	     case TRAPDOOR:	if (!Can_dig_down(&u.uz)) rtrap = NO_TRAP;
142.  				break;
143.  	     case LEVEL_TELEP:
144.  	     case TELEP_TRAP:	if (level.flags.noteleport) rtrap = NO_TRAP;
145.  				break;
146.  	     case ROLLING_BOULDER_TRAP:
147.  	     case ROCKTRAP:	if (In_endgame(&u.uz)) rtrap = NO_TRAP;
148.  				break;
149.  	    }
150.  	} while (rtrap == NO_TRAP);
151.  	return rtrap;
152.  }
153.  

get_location Edit

154.  /*
155.   * Coordinates in special level files are handled specially:
156.   *
157.   *	if x or y is -11, we generate a random coordinate.
158.   *	if x or y is between -1 and -10, we read one from the corresponding
159.   *	register (x0, x1, ... x9).
160.   *	if x or y is nonnegative, we convert it from relative to the local map
161.   *	to global coordinates.
162.   *	The "humidity" flag is used to insure that engravings aren't
163.   *	created underwater, or eels on dry land.
164.   */
165.  #define DRY	0x1
166.  #define WET	0x2
167.  
168.  STATIC_DCL boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
169.  
170.  STATIC_OVL void
171.  get_location(x, y, humidity)
172.  schar *x, *y;
173.  int humidity;
174.  {
175.  	int cpt = 0;
176.  
177.  	if (*x >= 0) {			/* normal locations */
178.  		*x += xstart;
179.  		*y += ystart;
180.  	} else if (*x > -11) {		/* special locations */
181.  		*y = ystart + rloc_y[ - *y - 1];
182.  		*x = xstart + rloc_x[ - *x - 1];
183.  	} else {			/* random location */
184.  	    do {
185.  		*x = xstart + rn2((int)xsize);
186.  		*y = ystart + rn2((int)ysize);
187.  		if (is_ok_location(*x,*y,humidity)) break;
188.  	    } while (++cpt < 100);
189.  	    if (cpt >= 100) {
190.  		register int xx, yy;
191.  		/* last try */
192.  		for (xx = 0; xx < xsize; xx++)
193.  		    for (yy = 0; yy < ysize; yy++) {
194.  			*x = xstart + xx;
195.  			*y = ystart + yy;
196.  			if (is_ok_location(*x,*y,humidity)) goto found_it;
197.  		    }
198.  		panic("get_location:  can't find a place!");
199.  	    }
200.  	}
201.  found_it:;
202.  
203.  	if (!isok(*x,*y)) {
204.  	    impossible("get_location:  (%d,%d) out of bounds", *x, *y);
205.  	    *x = x_maze_max; *y = y_maze_max;
206.  	}
207.  }
208.  

is_ok_location Edit

209.  STATIC_OVL boolean
210.  is_ok_location(x, y, humidity)
211.  register schar x, y;
212.  register int humidity;
213.  {
214.  	register int typ;
215.  
216.  	if (Is_waterlevel(&u.uz)) return TRUE;	/* accept any spot */
217.  
218.  	if (humidity & DRY) {
219.  	    typ = levl[x][y].typ;
220.  	    if (typ == ROOM || typ == AIR ||
221.  		    typ == CLOUD || typ == ICE || typ == CORR)
222.  		return TRUE;
223.  	}
224.  	if (humidity & WET) {
225.  	    if (is_pool(x,y) || is_lava(x,y))
226.  		return TRUE;
227.  	}
228.  	return FALSE;
229.  }
230.  

sp_lev_shuffle Edit

231.  /*
232.   * Shuffle the registers for locations, objects or monsters
233.   */
234.  
235.  STATIC_OVL void
236.  sp_lev_shuffle(list1, list2, n)
237.  char list1[], list2[];
238.  int n;
239.  {
240.  	register int i, j;
241.  	register char k;
242.  
243.  	for (i = n - 1; i > 0; i--) {
244.  		if ((j = rn2(i + 1)) == i) continue;
245.  		k = list1[j];
246.  		list1[j] = list1[i];
247.  		list1[i] = k;
248.  		if (list2) {
249.  			k = list2[j];
250.  			list2[j] = list2[i];
251.  			list2[i] = k;
252.  		}
253.  	}
254.  }
255.  

get_room_loc Edit

256.  /*
257.   * Get a relative position inside a room.
258.   * negative values for x or y means RANDOM!
259.   */
260.  
261.  STATIC_OVL void
262.  get_room_loc(x,y, croom)
263.  schar		*x, *y;
264.  struct mkroom	*croom;
265.  {
266.  	coord c;
267.  
268.  	if (*x <0 && *y <0) {
269.  		if (somexy(croom, &c)) {
270.  			*x = c.x;
271.  			*y = c.y;
272.  		} else
273.  		    panic("get_room_loc : can't find a place!");
274.  	} else {
275.  		if (*x < 0)
276.  		    *x = rn2(croom->hx - croom->lx + 1);
277.  		if (*y < 0)
278.  		    *y = rn2(croom->hy - croom->ly + 1);
279.  		*x += croom->lx;
280.  		*y += croom->ly;
281.  	}
282.  }
283.  

get_free_room_loc Edit

284.  /*
285.   * Get a relative position inside a room.
286.   * negative values for x or y means RANDOM!
287.   */
288.  
289.  STATIC_OVL void
290.  get_free_room_loc(x,y, croom)
291.  schar		*x, *y;
292.  struct mkroom	*croom;
293.  {
294.  	schar try_x, try_y;
295.  	register int trycnt = 0;
296.  
297.  	do {
298.  	    try_x = *x,  try_y = *y;
299.  	    get_room_loc(&try_x, &try_y, croom);
300.  	} while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100);
301.  
302.  	if (trycnt > 100)
303.  	    panic("get_free_room_loc:  can't find a place!");
304.  	*x = try_x,  *y = try_y;
305.  }
306.  

check_room Edit

307.  boolean
308.  check_room(lowx, ddx, lowy, ddy, vault)
309.  xchar *lowx, *ddx, *lowy, *ddy;
310.  boolean vault;
311.  {
312.  	register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy;
313.  	register struct rm *lev;
314.  	int xlim, ylim, ymax;
315.  
316.  	xlim = XLIM + (vault ? 1 : 0);
317.  	ylim = YLIM + (vault ? 1 : 0);
318.  
319.  	if (*lowx < 3)		*lowx = 3;
320.  	if (*lowy < 2)		*lowy = 2;
321.  	if (hix > COLNO-3)	hix = COLNO-3;
322.  	if (hiy > ROWNO-3)	hiy = ROWNO-3;
323.  chk:
324.  	if (hix <= *lowx || hiy <= *lowy)	return FALSE;
325.  
326.  	/* check area around room (and make room smaller if necessary) */
327.  	for (x = *lowx - xlim; x<= hix + xlim; x++) {
328.  		if(x <= 0 || x >= COLNO) continue;
329.  		y = *lowy - ylim;	ymax = hiy + ylim;
330.  		if(y < 0) y = 0;
331.  		if(ymax >= ROWNO) ymax = (ROWNO-1);
332.  		lev = &levl[x][y];
333.  		for (; y <= ymax; y++) {
334.  			if (lev++->typ) {
335.  #ifdef DEBUG
336.  				if(!vault)
337.  				    debugpline("strange area [%d,%d] in check_room.",x,y);
338.  #endif
339.  				if (!rn2(3))	return FALSE;
340.  				if (x < *lowx)
341.  				    *lowx = x + xlim + 1;
342.  				else
343.  				    hix = x - xlim - 1;
344.  				if (y < *lowy)
345.  				    *lowy = y + ylim + 1;
346.  				else
347.  				    hiy = y - ylim - 1;
348.  				goto chk;
349.  			}
350.  		}
351.  	}
352.  	*ddx = hix - *lowx;
353.  	*ddy = hiy - *lowy;
354.  	return TRUE;
355.  }
356.  

create_room Edit

357.  /*
358.   * Create a new room.
359.   * This is still very incomplete...
360.   */
361.  
362.  boolean
363.  create_room(x,y,w,h,xal,yal,rtype,rlit)
364.  xchar	x,y;
365.  xchar	w,h;
366.  xchar	xal,yal;
367.  xchar	rtype, rlit;
368.  {
369.  	xchar	xabs, yabs;
370.  	int	wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
371.  	NhRect	*r1 = 0, r2;
372.  	int	trycnt = 0;
373.  	boolean	vault = FALSE;
374.  	int	xlim = XLIM, ylim = YLIM;
375.  
376.  	if (rtype == -1)	/* Is the type random ? */
377.  	    rtype = OROOM;
378.  
379.  	if (rtype == VAULT) {
380.  		vault = TRUE;
381.  		xlim++;
382.  		ylim++;
383.  	}
384.  
385.  	/* on low levels the room is lit (usually) */
386.  	/* some other rooms may require lighting */
387.  
388.  	/* is light state random ? */
389.  	if (rlit == -1)
390.  	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
391.  
392.  	/*
393.  	 * Here we will try to create a room. If some parameters are
394.  	 * random we are willing to make several try before we give
395.  	 * it up.
396.  	 */
397.  	do {
398.  		xchar xborder, yborder;
399.  		wtmp = w; htmp = h;
400.  		xtmp = x; ytmp = y;
401.  		xaltmp = xal; yaltmp = yal;
402.  
403.  		/* First case : a totaly random room */
404.  
405.  		if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 &&
406.  		   yaltmp < 0) || vault) {
407.  			xchar hx, hy, lx, ly, dx, dy;
408.  			r1 = rnd_rect(); /* Get a random rectangle */
409.  
410.  			if (!r1) { /* No more free rectangles ! */
411.  #ifdef DEBUG
412.  				debugpline("No more rects...");
413.  #endif
414.  				return FALSE;
415.  			}
416.  			hx = r1->hx;
417.  			hy = r1->hy;
418.  			lx = r1->lx;
419.  			ly = r1->ly;
420.  			if (vault)
421.  			    dx = dy = 1;
422.  			else {
423.  				dx = 2 + rn2((hx-lx > 28) ? 12 : 8);
424.  				dy = 2 + rn2(4);
425.  				if(dx*dy > 50)
426.  				    dy = 50/dx;
427.  			}
428.  			xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1;
429.  			yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1;
430.  			if(hx-lx < dx + 3 + xborder ||
431.  			   hy-ly < dy + 3 + yborder) {
432.  				r1 = 0;
433.  				continue;
434.  			}
435.  			xabs = lx + (lx > 0 ? xlim : 3)
436.  			    + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1);
437.  			yabs = ly + (ly > 0 ? ylim : 2)
438.  			    + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1);
439.  			if (ly == 0 && hy >= (ROWNO-1) &&
440.  			    (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) {
441.  			    yabs = rn1(3, 2);
442.  			    if(nroom < 4 && dy>1) dy--;
443.  		        }
444.  			if (!check_room(&xabs, &dx, &yabs, &dy, vault)) {
445.  				r1 = 0;
446.  				continue;
447.  			}
448.  			wtmp = dx+1;
449.  			htmp = dy+1;
450.  			r2.lx = xabs-1; r2.ly = yabs-1;
451.  			r2.hx = xabs + wtmp;
452.  			r2.hy = yabs + htmp;
453.  		} else {	/* Only some parameters are random */
454.  			int rndpos = 0;
455.  			if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
456.  				xtmp = rnd(5);
457.  				ytmp = rnd(5);
458.  				rndpos = 1;
459.  			}
460.  			if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */
461.  				wtmp = rn1(15, 3);
462.  				htmp = rn1(8, 2);
463.  			}
464.  			if (xaltmp == -1) /* Horizontal alignment is RANDOM */
465.  			    xaltmp = rnd(3);
466.  			if (yaltmp == -1) /* Vertical alignment is RANDOM */
467.  			    yaltmp = rnd(3);
468.  
469.  			/* Try to generate real (absolute) coordinates here! */
470.  
471.  			xabs = (((xtmp-1) * COLNO) / 5) + 1;
472.  			yabs = (((ytmp-1) * ROWNO) / 5) + 1;
473.  			switch (xaltmp) {
474.  			      case LEFT:
475.  				break;
476.  			      case RIGHT:
477.  				xabs += (COLNO / 5) - wtmp;
478.  				break;
479.  			      case CENTER:
480.  				xabs += ((COLNO / 5) - wtmp) / 2;
481.  				break;
482.  			}
483.  			switch (yaltmp) {
484.  			      case TOP:
485.  				break;
486.  			      case BOTTOM:
487.  				yabs += (ROWNO / 5) - htmp;
488.  				break;
489.  			      case CENTER:
490.  				yabs += ((ROWNO / 5) - htmp) / 2;
491.  				break;
492.  			}
493.  
494.  			if (xabs + wtmp - 1 > COLNO - 2)
495.  			    xabs = COLNO - wtmp - 3;
496.  			if (xabs < 2)
497.  			    xabs = 2;
498.  			if (yabs + htmp - 1> ROWNO - 2)
499.  			    yabs = ROWNO - htmp - 3;
500.  			if (yabs < 2)
501.  			    yabs = 2;
502.  
503.  			/* Try to find a rectangle that fit our room ! */
504.  
505.  			r2.lx = xabs-1; r2.ly = yabs-1;
506.  			r2.hx = xabs + wtmp + rndpos;
507.  			r2.hy = yabs + htmp + rndpos;
508.  			r1 = get_rect(&r2);
509.  		}
510.  	} while (++trycnt <= 100 && !r1);
511.  	if (!r1) {	/* creation of room failed ? */
512.  		return FALSE;
513.  	}
514.  	split_rects(r1, &r2);
515.  
516.  	if (!vault) {
517.  		smeq[nroom] = nroom;
518.  		add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1,
519.  			 rlit, rtype, FALSE);
520.  	} else {
521.  		rooms[nroom].lx = xabs;
522.  		rooms[nroom].ly = yabs;
523.  	}
524.  	return TRUE;
525.  }
526.  

create_subroom Edit

527.  /*
528.   * Create a subroom in room proom at pos x,y with width w & height h.
529.   * x & y are relative to the parent room.
530.   */
531.  
532.  STATIC_OVL boolean
533.  create_subroom(proom, x, y, w,  h, rtype, rlit)
534.  struct mkroom *proom;
535.  xchar x,y;
536.  xchar w,h;
537.  xchar rtype, rlit;
538.  {
539.  	xchar width, height;
540.  
541.  	width = proom->hx - proom->lx + 1;
542.  	height = proom->hy - proom->ly + 1;
543.  
544.  	/* There is a minimum size for the parent room */
545.  	if (width < 4 || height < 4)
546.  	    return FALSE;
547.  
548.  	/* Check for random position, size, etc... */
549.  
550.  	if (w == -1)
551.  	    w = rnd(width - 3);
552.  	if (h == -1)
553.  	    h = rnd(height - 3);
554.  	if (x == -1)
555.  	    x = rnd(width - w - 1) - 1;
556.  	if (y == -1)
557.  	    y = rnd(height - h - 1) - 1;
558.  	if (x == 1)
559.  	    x = 0;
560.  	if (y == 1)
561.  	    y = 0;
562.  	if ((x + w + 1) == width)
563.  	    x++;
564.  	if ((y + h + 1) == height)
565.  	    y++;
566.  	if (rtype == -1)
567.  	    rtype = OROOM;
568.  	if (rlit == -1)
569.  	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
570.  	add_subroom(proom, proom->lx + x, proom->ly + y,
571.  		    proom->lx + x + w - 1, proom->ly + y + h - 1,
572.  		    rlit, rtype, FALSE);
573.  	return TRUE;
574.  }
575.  

create_door Edit

576.  /*
577.   * Create a new door in a room.
578.   * It's placed on a wall (north, south, east or west).
579.   */
580.  
581.  STATIC_OVL void
582.  create_door(dd, broom)
583.  room_door *dd;
584.  struct mkroom *broom;
585.  {
586.  	int	x, y;
587.  	int	trycnt = 0;
588.  
589.  	if (dd->secret == -1)
590.  	    dd->secret = rn2(2);
591.  
592.  	if (dd->mask == -1) {
593.  		/* is it a locked door, closed, or a doorway? */
594.  		if (!dd->secret) {
595.  			if(!rn2(3)) {
596.  				if(!rn2(5))
597.  				    dd->mask = D_ISOPEN;
598.  				else if(!rn2(6))
599.  				    dd->mask = D_LOCKED;
600.  				else
601.  				    dd->mask = D_CLOSED;
602.  				if (dd->mask != D_ISOPEN && !rn2(25))
603.  				    dd->mask |= D_TRAPPED;
604.  			} else
605.  			    dd->mask = D_NODOOR;
606.  		} else {
607.  			if(!rn2(5))	dd->mask = D_LOCKED;
608.  			else		dd->mask = D_CLOSED;
609.  
610.  			if(!rn2(20)) dd->mask |= D_TRAPPED;
611.  		}
612.  	}
613.  
614.  	do {
615.  		register int dwall, dpos;
616.  
617.  		dwall = dd->wall;
618.  		if (dwall == -1)	/* The wall is RANDOM */
619.  		    dwall = 1 << rn2(4);
620.  
621.  		dpos = dd->pos;
622.  		if (dpos == -1)	/* The position is RANDOM */
623.  		    dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?
624.  			    (broom->hy - broom->ly) : (broom->hx - broom->lx));
625.  
626.  		/* Convert wall and pos into an absolute coordinate! */
627.  
628.  		switch (dwall) {
629.  		      case W_NORTH:
630.  			y = broom->ly - 1;
631.  			x = broom->lx + dpos;
632.  			break;
633.  		      case W_SOUTH:
634.  			y = broom->hy + 1;
635.  			x = broom->lx + dpos;
636.  			break;
637.  		      case W_WEST:
638.  			x = broom->lx - 1;
639.  			y = broom->ly + dpos;
640.  			break;
641.  		      case W_EAST:
642.  			x = broom->hx + 1;
643.  			y = broom->ly + dpos;
644.  			break;
645.  		      default:
646.  			x = y = 0;
647.  			panic("create_door: No wall for door!");
648.  			break;
649.  		}
650.  		if (okdoor(x,y))
651.  		    break;
652.  	} while (++trycnt <= 100);
653.  	if (trycnt > 100) {
654.  		impossible("create_door: Can't find a proper place!");
655.  		return;
656.  	}
657.  	add_door(x,y,broom);
658.  	levl[x][y].typ = (dd->secret ? SDOOR : DOOR);
659.  	levl[x][y].doormask = dd->mask;
660.  }
661.  

create_secret_door Edit

662.  /*
663.   * Create a secret door in croom on any one of the specified walls.
664.   */
665.  void
666.  create_secret_door(croom, walls)
667.      struct mkroom *croom;
668.      xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
669.  {
670.      xchar sx, sy; /* location of the secret door */
671.      int count;
672.  
673.      for(count = 0; count < 100; count++) {
674.  	sx = rn1(croom->hx - croom->lx + 1, croom->lx);
675.  	sy = rn1(croom->hy - croom->ly + 1, croom->ly);
676.  
677.  	switch(rn2(4)) {
678.  	case 0:  /* top */
679.  	    if(!(walls & W_NORTH)) continue;
680.  	    sy = croom->ly-1; break;
681.  	case 1: /* bottom */
682.  	    if(!(walls & W_SOUTH)) continue;
683.  	    sy = croom->hy+1; break;
684.  	case 2: /* left */
685.  	    if(!(walls & W_EAST)) continue;
686.  	    sx = croom->lx-1; break;
687.  	case 3: /* right */
688.  	    if(!(walls & W_WEST)) continue;
689.  	    sx = croom->hx+1; break;
690.  	}
691.  
692.  	if(okdoor(sx,sy)) {
693.  	    levl[sx][sy].typ = SDOOR;
694.  	    levl[sx][sy].doormask = D_CLOSED;
695.  	    add_door(sx,sy,croom);
696.  	    return;
697.  	}
698.      }
699.  
700.      impossible("couldn't create secret door on any walls 0x%x", walls);
701.  }
702.  

create_trap Edit

703.  /*
704.   * Create a trap in a room.
705.   */
706.  
707.  STATIC_OVL void
708.  create_trap(t,croom)
709.  trap	*t;
710.  struct mkroom	*croom;
711.  {
712.      schar	x,y;
713.      coord	tm;
714.  
715.      if (rn2(100) < t->chance) {
716.  	x = t->x;
717.  	y = t->y;
718.  	if (croom)
719.  	    get_free_room_loc(&x, &y, croom);
720.  	else
721.  	    get_location(&x, &y, DRY);
722.  
723.  	tm.x = x;
724.  	tm.y = y;
725.  
726.  	mktrap(t->type, 1, (struct mkroom*) 0, &tm);
727.      }
728.  }
729.  

noncoalignment Edit

730.  /*
731.   * Create a monster in a room.
732.   */
733.  
734.  STATIC_OVL int
735.  noncoalignment(alignment)
736.  aligntyp alignment;
737.  {
738.  	int k;
739.  
740.  	k = rn2(2);
741.  	if (!alignment)
742.  		return(k ? -1 : 1);
743.  	return(k ? -alignment : 0);
744.  }
745.  

create_monster Edit

746.  STATIC_OVL void
747.  create_monster(m,croom)
748.  monster	*m;
749.  struct mkroom	*croom;
750.  {
751.      struct monst *mtmp;
752.      schar x, y;
753.      char class;
754.      aligntyp amask;
755.      coord cc;
756.      struct permonst *pm;
757.      unsigned g_mvflags;
758.  
759.      if (rn2(100) < m->chance) {
760.  
761.  	if (m->class >= 0)
762.  	    class = (char) def_char_to_monclass((char)m->class);
763.  	else if (m->class > -11)
764.  	    class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
765.  	else
766.  	    class = 0;
767.  
768.  	if (class == MAXMCLASSES)
769.  	    panic("create_monster: unknown monster class '%c'", m->class);
770.  
771.  	amask = (m->align == AM_SPLEV_CO) ?
772.  			Align2amask(u.ualignbase[A_ORIGINAL]) :
773.  		(m->align == AM_SPLEV_NONCO) ?
774.  			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) :
775.  		(m->align <= -11) ? induced_align(80) :
776.  		(m->align < 0 ? ralign[-m->align-1] : m->align);
777.  
778.  	if (!class)
779.  	    pm = (struct permonst *) 0;
780.  	else if (m->id != NON_PM) {
781.  	    pm = &mons[m->id];
782.  	    g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
783.  	    if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT))
784.  		goto m_done;
785.  	    else if (g_mvflags & G_GONE)	/* genocided or extinct */
786.  		pm = (struct permonst *) 0;	/* make random monster */
787.  	} else {
788.  	    pm = mkclass(class,G_NOGEN);
789.  	    /* if we can't get a specific monster type (pm == 0) then the
790.  	       class has been genocided, so settle for a random monster */
791.  	}
792.  	if (In_mines(&u.uz) && pm && your_race(pm) &&
793.  			(Race_if(PM_DWARF) || Race_if(PM_GNOME)) && rn2(3))
794.  	    pm = (struct permonst *) 0;
795.  
796.  	x = m->x;
797.  	y = m->y;
798.  	if (croom)
799.  	    get_room_loc(&x, &y, croom);
800.  	else {
801.  	    if (!pm || !is_swimmer(pm))
802.  		get_location(&x, &y, DRY);
803.  	    else if (pm->mlet == S_EEL)
804.  		get_location(&x, &y, WET);
805.  	    else
806.  		get_location(&x, &y, DRY|WET);
807.  	}
808.  	/* try to find a close place if someone else is already there */
809.  	if (MON_AT(x,y) && enexto(&cc, x, y, pm))
810.  	    x = cc.x,  y = cc.y;
811.  
812.  	if(m->align != -12)
813.  	    mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
814.  	else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
815.  	         mtmp = mk_mplayer(pm, x, y, FALSE);
816.  	else mtmp = makemon(pm, x, y, NO_MM_FLAGS);
817.  
818.  	if (mtmp) {
819.  	    /* handle specific attributes for some special monsters */
820.  	    if (m->name.str) mtmp = christen_monst(mtmp, m->name.str);
821.  
822.  	    /*
823.  	     * This is currently hardwired for mimics only.  It should
824.  	     * eventually be expanded.
825.  	     */
826.  	    if (m->appear_as.str && mtmp->data->mlet == S_MIMIC) {
827.  		int i;
828.  
829.  		switch (m->appear) {
830.  		    case M_AP_NOTHING:
831.  			impossible(
832.  		"create_monster: mon has an appearance, \"%s\", but no type",
833.  				m->appear_as.str);
834.  			break;
835.  
836.  		    case M_AP_FURNITURE:
837.  			for (i = 0; i < MAXPCHARS; i++)
838.  			    if (!strcmp(defsyms[i].explanation,
839.  					m->appear_as.str))
840.  				break;
841.  			if (i == MAXPCHARS) {
842.  			    impossible(
843.  				"create_monster: can't find feature \"%s\"",
844.  				m->appear_as.str);
845.  			} else {
846.  			    mtmp->m_ap_type = M_AP_FURNITURE;
847.  			    mtmp->mappearance = i;
848.  			}
849.  			break;
850.  
851.  		    case M_AP_OBJECT:
852.  			for (i = 0; i < NUM_OBJECTS; i++)
853.  			    if (OBJ_NAME(objects[i]) &&
854.  				!strcmp(OBJ_NAME(objects[i]),m->appear_as.str))
855.  				break;
856.  			if (i == NUM_OBJECTS) {
857.  			    impossible(
858.  				"create_monster: can't find object \"%s\"",
859.  				m->appear_as.str);
860.  			} else {
861.  			    mtmp->m_ap_type = M_AP_OBJECT;
862.  			    mtmp->mappearance = i;
863.  			}
864.  			break;
865.  
866.  		    case M_AP_MONSTER:
867.  			/* note: mimics don't appear as monsters! */
868.  			/*	 (but chameleons can :-)	  */
869.  		    default:
870.  			impossible(
871.  		"create_monster: unimplemented mon appear type [%d,\"%s\"]",
872.  				m->appear, m->appear_as.str);
873.  			break;
874.  		}
875.  		if (does_block(x, y, &levl[x][y]))
876.  		    block_point(x, y);
877.  	    }
878.  
879.  	    if (m->peaceful >= 0) {
880.  		mtmp->mpeaceful = m->peaceful;
881.  		/* changed mpeaceful again; have to reset malign */
882.  		set_malign(mtmp);
883.  	    }
884.  	    if (m->asleep >= 0) {
885.  #ifdef UNIXPC
886.  		/* optimizer bug strikes again */
887.  		if (m->asleep)
888.  			mtmp->msleeping = 1;
889.  		else
890.  			mtmp->msleeping = 0;
891.  #else
892.  		mtmp->msleeping = m->asleep;
893.  #endif
894.  	    }
895.  	}
896.  
897.      }		/* if (rn2(100) < m->chance) */
898.   m_done:
899.      Free(m->name.str);
900.      Free(m->appear_as.str);
901.  }
902.  

create_object Edit

903.  /*
904.   * Create an object in a room.
905.   */
906.  
907.  STATIC_OVL void
908.  create_object(o,croom)
909.  object	*o;
910.  struct mkroom	*croom;
911.  {
912.      struct obj *otmp;
913.      schar x, y;
914.      char c;
915.      boolean named;	/* has a name been supplied in level description? */
916.  
917.      if (rn2(100) < o->chance) {
918.  	named = o->name.str ? TRUE : FALSE;
919.  
920.  	x = o->x; y = o->y;
921.  	if (croom)
922.  	    get_room_loc(&x, &y, croom);
923.  	else
924.  	    get_location(&x, &y, DRY);
925.  
926.  	if (o->class >= 0)
927.  	    c = o->class;
928.  	else if (o->class > -11)
929.  	    c = robjects[ -(o->class+1)];
930.  	else
931.  	    c = 0;
932.  
933.  	if (!c)
934.  	    otmp = mkobj_at(RANDOM_CLASS, x, y, !named);
935.  	else if (o->id != -1)
936.  	    otmp = mksobj_at(o->id, x, y, TRUE, !named);
937.  	else {
938.  	    /*
939.  	     * The special levels are compiled with the default "text" object
940.  	     * class characters.  We must convert them to the internal format.
941.  	     */
942.  	    char oclass = (char) def_char_to_objclass(c);
943.  
944.  	    if (oclass == MAXOCLASSES)
945.  		panic("create_object:  unexpected object class '%c'",c);
946.  
947.  	    /* KMH -- Create piles of gold properly */
948.  	    if (oclass == COIN_CLASS)
949.  		otmp = mkgold(0L, x, y);
950.  	    else
951.  		otmp = mkobj_at(oclass, x, y, !named);
952.  	}
953.  
954.  	if (o->spe != -127)	/* That means NOT RANDOM! */
955.  	    otmp->spe = (schar)o->spe;
956.  
957.  	switch (o->curse_state) {
958.  	      case 1:	bless(otmp); break; /* BLESSED */
959.  	      case 2:	unbless(otmp); uncurse(otmp); break; /* uncursed */
960.  	      case 3:	curse(otmp); break; /* CURSED */
961.  	      default:	break;	/* Otherwise it's random and we're happy
962.  				 * with what mkobj gave us! */
963.  	}
964.  
965.  	/*	corpsenm is "empty" if -1, random if -2, otherwise specific */
966.  	if (o->corpsenm == NON_PM - 1) otmp->corpsenm = rndmonnum();
967.  	else if (o->corpsenm != NON_PM) otmp->corpsenm = o->corpsenm;
968.  
969.  	/* assume we wouldn't be given an egg corpsenm unless it was
970.  	   hatchable */
971.  	if (otmp->otyp == EGG && otmp->corpsenm != NON_PM) {
972.  	    if (dead_species(otmp->otyp, TRUE))
973.  		kill_egg(otmp);	/* make sure nothing hatches */
974.  	    else
975.  		attach_egg_hatch_timeout(otmp);	/* attach new hatch timeout */
976.  	}
977.  
978.  	if (named)
979.  	    otmp = oname(otmp, o->name.str);
980.  
981.  	switch(o->containment) {
982.  	    static struct obj *container = 0;
983.  
984.  	    /* contents */
985.  	    case 1:
986.  		if (!container) {
987.  		    impossible("create_object: no container");
988.  		    break;
989.  		}
990.  		remove_object(otmp);
991.  		(void) add_to_container(container, otmp);
992.  		goto o_done;		/* don't stack, but do other cleanup */
993.  	    /* container */
994.  	    case 2:
995.  		delete_contents(otmp);
996.  		container = otmp;
997.  		break;
998.  	    /* nothing */
999.  	    case 0: break;
1000. 
1001. 	    default: impossible("containment type %d?", (int) o->containment);
1002. 	}
1003. 
1004. 	/* Medusa level special case: statues are petrified monsters, so they
1005. 	 * are not stone-resistant and have monster inventory.  They also lack
1006. 	 * other contents, but that can be specified as an empty container.
1007. 	 */
1008. 	if (o->id == STATUE && Is_medusa_level(&u.uz) &&
1009. 		    o->corpsenm == NON_PM) {
1010. 	    struct monst *was;
1011. 	    struct obj *obj;
1012. 	    int wastyp;
1013. 
1014. 	    /* Named random statues are of player types, and aren't stone-
1015. 	     * resistant (if they were, we'd have to reset the name as well as
1016. 	     * setting corpsenm).
1017. 	     */
1018. 	    for (wastyp = otmp->corpsenm; ; wastyp = rndmonnum()) {
1019. 		/* makemon without rndmonst() might create a group */
1020. 		was = makemon(&mons[wastyp], 0, 0, NO_MM_FLAGS);
1021. 		if (!resists_ston(was)) break;
1022. 		mongone(was);
1023. 	    }
1024. 	    otmp->corpsenm = wastyp;
1025. 	    while(was->minvent) {
1026. 		obj = was->minvent;
1027. 		obj->owornmask = 0;
1028. 		obj_extract_self(obj);
1029. 		(void) add_to_container(otmp, obj);
1030. 	    }
1031. 	    otmp->owt = weight(otmp);
1032. 	    mongone(was);
1033. 	}
1034. 
1035. 	stackobj(otmp);
1036. 
1037.     }		/* if (rn2(100) < o->chance) */
1038.  o_done:
1039.     Free(o->name.str);
1040. }
1041. 

create_engraving Edit

1042. /*
1043.  * Randomly place a specific engraving, then release its memory.
1044.  */
1045. STATIC_OVL void
1046. create_engraving(e, croom)
1047. engraving *e;
1048. struct mkroom *croom;
1049. {
1050. 	xchar x, y;
1051. 
1052. 	x = e->x,  y = e->y;
1053. 	if (croom)
1054. 	    get_room_loc(&x, &y, croom);
1055. 	else
1056. 	    get_location(&x, &y, DRY);
1057. 
1058. 	make_engr_at(x, y, e->engr.str, 0L, e->etype);
1059. 	free((genericptr_t) e->engr.str);
1060. }
1061. 

create_stairs Edit

1062. /*
1063.  * Create stairs in a room.
1064.  *
1065.  */
1066. 
1067. STATIC_OVL void
1068. create_stairs(s,croom)
1069. stair	*s;
1070. struct mkroom	*croom;
1071. {
1072. 	schar		x,y;
1073. 
1074. 	x = s->x; y = s->y;
1075. 	get_free_room_loc(&x, &y, croom);
1076. 	mkstairs(x,y,(char)s->up, croom);
1077. }
1078. 

create_altar Edit

1079. /*
1080.  * Create an altar in a room.
1081.  */
1082. 
1083. STATIC_OVL void
1084. create_altar(a, croom)
1085. 	altar		*a;
1086. 	struct mkroom	*croom;
1087. {
1088. 	schar		sproom,x,y;
1089. 	aligntyp	amask;
1090. 	boolean		croom_is_temple = TRUE;
1091. 	int oldtyp; 
1092. 
1093. 	x = a->x; y = a->y;
1094. 
1095. 	if (croom) {
1096. 	    get_free_room_loc(&x, &y, croom);
1097. 	    if (croom->rtype != TEMPLE)
1098. 		croom_is_temple = FALSE;
1099. 	} else {
1100. 	    get_location(&x, &y, DRY);
1101. 	    if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
1102. 		croom = &rooms[sproom - ROOMOFFSET];
1103. 	    else
1104. 		croom_is_temple = FALSE;
1105. 	}
1106. 
1107. 	/* check for existing features */
1108. 	oldtyp = levl[x][y].typ;
1109. 	if (oldtyp == STAIRS || oldtyp == LADDER)
1110. 	    return;
1111. 
1112. 	a->x = x;
1113. 	a->y = y;
1114. 
1115. 	/* Is the alignment random ?
1116. 	 * If so, it's an 80% chance that the altar will be co-aligned.
1117. 	 *
1118. 	 * The alignment is encoded as amask values instead of alignment
1119. 	 * values to avoid conflicting with the rest of the encoding,
1120. 	 * shared by many other parts of the special level code.
1121. 	 */
1122. 
1123. 	amask = (a->align == AM_SPLEV_CO) ?
1124. 			Align2amask(u.ualignbase[A_ORIGINAL]) :
1125. 		(a->align == AM_SPLEV_NONCO) ?
1126. 			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) :
1127. 		(a->align == -11) ? induced_align(80) :
1128. 		(a->align < 0 ? ralign[-a->align-1] : a->align);
1129. 
1130. 	levl[x][y].typ = ALTAR;
1131. 	levl[x][y].altarmask = amask;
1132. 
1133. 	if (a->shrine < 0) a->shrine = rn2(2);	/* handle random case */
1134. 
1135. 	if (oldtyp == FOUNTAIN)
1136. 	    level.flags.nfountains--;
1137. 	else if (oldtyp == SINK)
1138. 	    level.flags.nsinks--;
1139. 
1140. 	if (!croom_is_temple || !a->shrine) return;
1141. 
1142. 	if (a->shrine) {	/* Is it a shrine  or sanctum? */
1143. 	    priestini(&u.uz, croom, x, y, (a->shrine > 1));
1144. 	    levl[x][y].altarmask |= AM_SHRINE;
1145. 	    level.flags.has_temple = TRUE;
1146. 	}
1147. }
1148. 

create_gold Edit

1149. /*
1150.  * Create a gold pile in a room.
1151.  */
1152. 
1153. STATIC_OVL void
1154. create_gold(g,croom)
1155. gold *g;
1156. struct mkroom	*croom;
1157. {
1158. 	schar		x,y;
1159. 
1160. 	x = g->x; y= g->y;
1161. 	if (croom)
1162. 	    get_room_loc(&x, &y, croom);
1163. 	else
1164. 	    get_location(&x, &y, DRY);
1165. 
1166. 	if (g->amount == -1)
1167. 	    g->amount = rnd(200);
1168. 	(void) mkgold((long) g->amount, x, y);
1169. }
1170. 

create_feature Edit

1171. /*
1172.  * Create a feature (e.g a fountain) in a room.
1173.  */
1174. 
1175. STATIC_OVL void
1176. create_feature(fx, fy, croom, typ)
1177. int		fx, fy;
1178. struct mkroom	*croom;
1179. int		typ;
1180. {
1181. 	schar		x,y;
1182. 	int		trycnt = 0;
1183. 
1184. 	x = fx;  y = fy;
1185. 	if (croom) {
1186. 	    if (x < 0 && y < 0)
1187. 		do {
1188. 		    x = -1;  y = -1;
1189. 		    get_room_loc(&x, &y, croom);
1190. 		} while (++trycnt <= 200 && occupied(x,y));
1191. 	    else
1192. 		get_room_loc(&x, &y, croom);
1193. 	    if(trycnt > 200)
1194. 		return;
1195. 	} else {
1196. 	    get_location(&x, &y, DRY);
1197. 	}
1198. 	/* Don't cover up an existing feature (particularly randomly
1199. 	   placed stairs).  However, if the _same_ feature is already
1200. 	   here, it came from the map drawing and we still need to
1201. 	   update the special counters. */
1202. 	if (IS_FURNITURE(levl[x][y].typ) && levl[x][y].typ != typ)
1203. 	    return;
1204. 
1205. 	levl[x][y].typ = typ;
1206. 	if (typ == FOUNTAIN)
1207. 	    level.flags.nfountains++;
1208. 	else if (typ == SINK)
1209. 	    level.flags.nsinks++;
1210. }
1211. 

search_door Edit

1212. /*
1213.  * Search for a door in a room on a specified wall.
1214.  */
1215. 
1216. STATIC_OVL boolean
1217. search_door(croom,x,y,wall,cnt)
1218. struct mkroom *croom;
1219. xchar *x, *y;
1220. xchar wall;
1221. int cnt;
1222. {
1223. 	int dx, dy;
1224. 	int xx,yy;
1225. 
1226. 	switch(wall) {
1227. 	      case W_NORTH:
1228. 		dy = 0; dx = 1;
1229. 		xx = croom->lx;
1230. 		yy = croom->hy + 1;
1231. 		break;
1232. 	      case W_SOUTH:
1233. 		dy = 0; dx = 1;
1234. 		xx = croom->lx;
1235. 		yy = croom->ly - 1;
1236. 		break;
1237. 	      case W_EAST:
1238. 		dy = 1; dx = 0;
1239. 		xx = croom->hx + 1;
1240. 		yy = croom->ly;
1241. 		break;
1242. 	      case W_WEST:
1243. 		dy = 1; dx = 0;
1244. 		xx = croom->lx - 1;
1245. 		yy = croom->ly;
1246. 		break;
1247. 	      default:
1248. 		dx = dy = xx = yy = 0;
1249. 		panic("search_door: Bad wall!");
1250. 		break;
1251. 	}
1252. 	while (xx <= croom->hx+1 && yy <= croom->hy+1) {
1253. 		if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
1254. 			*x = xx;
1255. 			*y = yy;
1256. 			if (cnt-- <= 0)
1257. 			    return TRUE;
1258. 		}
1259. 		xx += dx;
1260. 		yy += dy;
1261. 	}
1262. 	return FALSE;
1263. }
1264. 

dig_corridor Edit

1265. /*
1266.  * Dig a corridor between two points.
1267.  */
1268. 
1269. boolean
1270. dig_corridor(org,dest,nxcor,ftyp,btyp)
1271. coord *org, *dest;
1272. boolean nxcor;
1273. schar ftyp, btyp;
1274. {
1275. 	register int dx=0, dy=0, dix, diy, cct;
1276. 	register struct rm *crm;
1277. 	register int tx, ty, xx, yy;
1278. 
1279. 	xx = org->x;  yy = org->y;
1280. 	tx = dest->x; ty = dest->y;
1281. 	if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 ||
1282. 	    xx > COLNO-1 || tx > COLNO-1 ||
1283. 	    yy > ROWNO-1 || ty > ROWNO-1) {
1284. #ifdef DEBUG
1285. 		debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).",
1286. 			   xx,yy,tx,ty);
1287. #endif
1288. 		return FALSE;
1289. 	}
1290. 	if (tx > xx)		dx = 1;
1291. 	else if (ty > yy)	dy = 1;
1292. 	else if (tx < xx)	dx = -1;
1293. 	else			dy = -1;
1294. 
1295. 	xx -= dx;
1296. 	yy -= dy;
1297. 	cct = 0;
1298. 	while(xx != tx || yy != ty) {
1299. 	    /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
1300. 	    if(cct++ > 500 || (nxcor && !rn2(35)))
1301. 		return FALSE;
1302. 
1303. 	    xx += dx;
1304. 	    yy += dy;
1305. 
1306. 	    if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1)
1307. 		return FALSE;		/* impossible */
1308. 
1309. 	    crm = &levl[xx][yy];
1310. 	    if(crm->typ == btyp) {
1311. 		if(ftyp != CORR || rn2(100)) {
1312. 			crm->typ = ftyp;
1313. 			if(nxcor && !rn2(50))
1314. 				(void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE);
1315. 		} else {
1316. 			crm->typ = SCORR;
1317. 		}
1318. 	    } else
1319. 	    if(crm->typ != ftyp && crm->typ != SCORR) {
1320. 		/* strange ... */
1321. 		return FALSE;
1322. 	    }
1323. 
1324. 	    /* find next corridor position */
1325. 	    dix = abs(xx-tx);
1326. 	    diy = abs(yy-ty);
1327. 
1328. 	    /* do we have to change direction ? */
1329. 	    if(dy && dix > diy) {
1330. 		register int ddx = (xx > tx) ? -1 : 1;
1331. 
1332. 		crm = &levl[xx+ddx][yy];
1333. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
1334. 		    dx = ddx;
1335. 		    dy = 0;
1336. 		    continue;
1337. 		}
1338. 	    } else if(dx && diy > dix) {
1339. 		register int ddy = (yy > ty) ? -1 : 1;
1340. 
1341. 		crm = &levl[xx][yy+ddy];
1342. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
1343. 		    dy = ddy;
1344. 		    dx = 0;
1345. 		    continue;
1346. 		}
1347. 	    }
1348. 
1349. 	    /* continue straight on? */
1350. 	    crm = &levl[xx+dx][yy+dy];
1351. 	    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
1352. 		continue;
1353. 
1354. 	    /* no, what must we do now?? */
1355. 	    if(dx) {
1356. 		dx = 0;
1357. 		dy = (ty < yy) ? -1 : 1;
1358. 	    } else {
1359. 		dy = 0;
1360. 		dx = (tx < xx) ? -1 : 1;
1361. 	    }
1362. 	    crm = &levl[xx+dx][yy+dy];
1363. 	    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
1364. 		continue;
1365. 	    dy = -dy;
1366. 	    dx = -dx;
1367. 	}
1368. 	return TRUE;
1369. }
1370. 

fix_stair_rooms Edit

1371. /*
1372.  * Disgusting hack: since special levels have their rooms filled before
1373.  * sorting the rooms, we have to re-arrange the speed values upstairs_room
1374.  * and dnstairs_room after the rooms have been sorted.  On normal levels,
1375.  * stairs don't get created until _after_ sorting takes place.
1376.  */
1377. STATIC_OVL void
1378. fix_stair_rooms()
1379. {
1380.     int i;
1381.     struct mkroom *croom;
1382. 
1383.     if(xdnstair &&
1384.        !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) &&
1385. 	 (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) {
1386. 	for(i=0; i < nroom; i++) {
1387. 	    croom = &rooms[i];
1388. 	    if((croom->lx <= xdnstair && xdnstair <= croom->hx) &&
1389. 	       (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
1390. 		dnstairs_room = croom;
1391. 		break;
1392. 	    }
1393. 	}
1394. 	if(i == nroom)
1395. 	    panic("Couldn't find dnstair room in fix_stair_rooms!");
1396.     }
1397.     if(xupstair &&
1398.        !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) &&
1399. 	 (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) {
1400. 	for(i=0; i < nroom; i++) {
1401. 	    croom = &rooms[i];
1402. 	    if((croom->lx <= xupstair && xupstair <= croom->hx) &&
1403. 	       (croom->ly <= yupstair && yupstair <= croom->hy)) {
1404. 		upstairs_room = croom;
1405. 		break;
1406. 	    }
1407. 	}
1408. 	if(i == nroom)
1409. 	    panic("Couldn't find upstair room in fix_stair_rooms!");
1410.     }
1411. }
1412. 

create_corridor Edit

1413. /*
1414.  * Corridors always start from a door. But it can end anywhere...
1415.  * Basically we search for door coordinates or for endpoints coordinates
1416.  * (from a distance).
1417.  */
1418. 
1419. STATIC_OVL void
1420. create_corridor(c)
1421. corridor	*c;
1422. {
1423. 	coord org, dest;
1424. 
1425. 	if (c->src.room == -1) {
1426. 		sort_rooms();
1427. 		fix_stair_rooms();
1428. 		makecorridors();
1429. 		return;
1430. 	}
1431. 
1432. 	if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall,
1433. 			 c->src.door))
1434. 	    return;
1435. 
1436. 	if (c->dest.room != -1) {
1437. 		if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y,
1438. 				c->dest.wall, c->dest.door))
1439. 		    return;
1440. 		switch(c->src.wall) {
1441. 		      case W_NORTH: org.y--; break;
1442. 		      case W_SOUTH: org.y++; break;
1443. 		      case W_WEST:  org.x--; break;
1444. 		      case W_EAST:  org.x++; break;
1445. 		}
1446. 		switch(c->dest.wall) {
1447. 		      case W_NORTH: dest.y--; break;
1448. 		      case W_SOUTH: dest.y++; break;
1449. 		      case W_WEST:  dest.x--; break;
1450. 		      case W_EAST:  dest.x++; break;
1451. 		}
1452. 		(void) dig_corridor(&org, &dest, FALSE, CORR, STONE);
1453. 	}
1454. }
1455. 
1456. 

fill_room Edit

1457. /*
1458.  * Fill a room (shop, zoo, etc...) with appropriate stuff.
1459.  */
1460. 
1461. void
1462. fill_room(croom, prefilled)
1463. struct mkroom *croom;
1464. boolean prefilled;
1465. {
1466. 	if (!croom || croom->rtype == OROOM)
1467. 	    return;
1468. 
1469. 	if (!prefilled) {
1470. 	    int x,y;
1471. 
1472. 	    /* Shop ? */
1473. 	    if (croom->rtype >= SHOPBASE) {
1474. 		    stock_room(croom->rtype - SHOPBASE, croom);
1475. 		    level.flags.has_shop = TRUE;
1476. 		    return;
1477. 	    }
1478. 
1479. 	    switch (croom->rtype) {
1480. 		case VAULT:
1481. 		    for (x=croom->lx;x<=croom->hx;x++)
1482. 			for (y=croom->ly;y<=croom->hy;y++)
1483. 			    (void) mkgold((long)rn1(abs(depth(&u.uz))*100, 51), x, y);
1484. 		    break;
1485. 		case COURT:
1486. 		case ZOO:
1487. 		case BEEHIVE:
1488. 		case MORGUE:
1489. 		case BARRACKS:
1490. 		    fill_zoo(croom);
1491. 		    break;
1492. 	    }
1493. 	}
1494. 	switch (croom->rtype) {
1495. 	    case VAULT:
1496. 		level.flags.has_vault = TRUE;
1497. 		break;
1498. 	    case ZOO:
1499. 		level.flags.has_zoo = TRUE;
1500. 		break;
1501. 	    case COURT:
1502. 		level.flags.has_court = TRUE;
1503. 		break;
1504. 	    case MORGUE:
1505. 		level.flags.has_morgue = TRUE;
1506. 		break;
1507. 	    case BEEHIVE:
1508. 		level.flags.has_beehive = TRUE;
1509. 		break;
1510. 	    case BARRACKS:
1511. 		level.flags.has_barracks = TRUE;
1512. 		break;
1513. 	    case TEMPLE:
1514. 		level.flags.has_temple = TRUE;
1515. 		break;
1516. 	    case SWAMP:
1517. 		level.flags.has_swamp = TRUE;
1518. 		break;
1519. 	}
1520. }
1521. 

free_rooms Edit

1522. STATIC_OVL void
1523. free_rooms(ro, n)
1524. room **ro;
1525. int n;
1526. {
1527. 	short j;
1528. 	room *r;
1529. 
1530. 	while(n--) {
1531. 		r = ro[n];
1532. 		Free(r->name);
1533. 		Free(r->parent);
1534. 		if ((j = r->ndoor) != 0) {
1535. 			while(j--)
1536. 			    Free(r->doors[j]);
1537. 			Free(r->doors);
1538. 		}
1539. 		if ((j = r->nstair) != 0) {
1540. 			while(j--)
1541. 			    Free(r->stairs[j]);
1542. 			Free(r->stairs);
1543. 		}
1544. 		if ((j = r->naltar) != 0) {
1545. 			while (j--)
1546. 			    Free(r->altars[j]);
1547. 			Free(r->altars);
1548. 		}
1549. 		if ((j = r->nfountain) != 0) {
1550. 			while(j--)
1551. 			    Free(r->fountains[j]);
1552. 			Free(r->fountains);
1553. 		}
1554. 		if ((j = r->nsink) != 0) {
1555. 			while(j--)
1556. 			    Free(r->sinks[j]);
1557. 			Free(r->sinks);
1558. 		}
1559. 		if ((j = r->npool) != 0) {
1560. 			while(j--)
1561. 			    Free(r->pools[j]);
1562. 			Free(r->pools);
1563. 		}
1564. 		if ((j = r->ntrap) != 0) {
1565. 			while (j--)
1566. 			    Free(r->traps[j]);
1567. 			Free(r->traps);
1568. 		}
1569. 		if ((j = r->nmonster) != 0) {
1570. 			while (j--)
1571. 				Free(r->monsters[j]);
1572. 			Free(r->monsters);
1573. 		}
1574. 		if ((j = r->nobject) != 0) {
1575. 			while (j--)
1576. 				Free(r->objects[j]);
1577. 			Free(r->objects);
1578. 		}
1579. 		if ((j = r->ngold) != 0) {
1580. 			while(j--)
1581. 			    Free(r->golds[j]);
1582. 			Free(r->golds);
1583. 		}
1584. 		if ((j = r->nengraving) != 0) {
1585. 			while (j--)
1586. 				Free(r->engravings[j]);
1587. 			Free(r->engravings);
1588. 		}
1589. 		Free(r);
1590. 	}
1591. 	Free(ro);
1592. }
1593. 

build_room Edit

1594. STATIC_OVL void
1595. build_room(r, pr)
1596. room *r, *pr;
1597. {
1598. 	boolean okroom;
1599. 	struct mkroom	*aroom;
1600. 	short i;
1601. 	xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
1602. 
1603. 	if(pr) {
1604. 		aroom = &subrooms[nsubroom];
1605. 		okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h,
1606. 					rtype, r->rlit);
1607. 	} else {
1608. 		aroom = &rooms[nroom];
1609. 		okroom = create_room(r->x, r->y, r->w, r->h, r->xalign,
1610. 				     r->yalign, rtype, r->rlit);
1611. 		r->mkr = aroom;
1612. 	}
1613. 
1614. 	if (okroom) {
1615. 		/* Create subrooms if necessary... */
1616. 		for(i=0; i < r->nsubroom; i++)
1617. 		    build_room(r->subrooms[i], r);
1618. 		/* And now we can fill the room! */
1619. 
1620. 		/* Priority to the stairs */
1621. 
1622. 		for(i=0; i <r->nstair; i++)
1623. 		    create_stairs(r->stairs[i], aroom);
1624. 
1625. 		/* Then to the various elements (sinks, etc..) */
1626. 		for(i = 0; i<r->nsink; i++)
1627. 		    create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK);
1628. 		for(i = 0; i<r->npool; i++)
1629. 		    create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL);
1630. 		for(i = 0; i<r->nfountain; i++)
1631. 		    create_feature(r->fountains[i]->x, r->fountains[i]->y,
1632. 				   aroom, FOUNTAIN);
1633. 		for(i = 0; i<r->naltar; i++)
1634. 		    create_altar(r->altars[i], aroom);
1635. 		for(i = 0; i<r->ndoor; i++)
1636. 		    create_door(r->doors[i], aroom);
1637. 
1638. 		/* The traps */
1639. 		for(i = 0; i<r->ntrap; i++)
1640. 		    create_trap(r->traps[i], aroom);
1641. 
1642. 		/* The monsters */
1643. 		for(i = 0; i<r->nmonster; i++)
1644. 		    create_monster(r->monsters[i], aroom);
1645. 
1646. 		/* The objects */
1647. 		for(i = 0; i<r->nobject; i++)
1648. 		    create_object(r->objects[i], aroom);
1649. 
1650. 		/* The gold piles */
1651. 		for(i = 0; i<r->ngold; i++)
1652. 		    create_gold(r->golds[i], aroom);
1653. 
1654. 		/* The engravings */
1655. 		for (i = 0; i < r->nengraving; i++)
1656. 		    create_engraving(r->engravings[i], aroom);
1657. 
1658. #ifdef SPECIALIZATION
1659. 		topologize(aroom,FALSE);		/* set roomno */
1660. #else
1661. 		topologize(aroom);			/* set roomno */
1662. #endif
1663. 		/* MRS - 07/04/91 - This is temporary but should result
1664. 		 * in proper filling of shops, etc.
1665. 		 * DLC - this can fail if corridors are added to this room
1666. 		 * at a later point.  Currently no good way to fix this.
1667. 		 */
1668. 		if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE);
1669. 	}
1670. }
1671. 

light_region Edit

1672. /*
1673.  * set lighting in a region that will not become a room.
1674.  */
1675. STATIC_OVL void
1676. light_region(tmpregion)
1677.     region  *tmpregion;
1678. {
1679.     register boolean litstate = tmpregion->rlit ? 1 : 0;
1680.     register int hiy = tmpregion->y2;
1681.     register int x, y;
1682.     register struct rm *lev;
1683.     int lowy = tmpregion->y1;
1684.     int lowx = tmpregion->x1, hix = tmpregion->x2;
1685. 
1686.     if(litstate) {
1687. 	/* adjust region size for walls, but only if lighted */
1688. 	lowx = max(lowx-1,1);
1689. 	hix = min(hix+1,COLNO-1);
1690. 	lowy = max(lowy-1,0);
1691. 	hiy = min(hiy+1, ROWNO-1);
1692.     }
1693.     for(x = lowx; x <= hix; x++) {
1694. 	lev = &levl[x][lowy];
1695. 	for(y = lowy; y <= hiy; y++) {
1696. 	    if (lev->typ != LAVAPOOL) /* this overrides normal lighting */
1697. 		lev->lit = litstate;
1698. 	    lev++;
1699. 	}
1700.     }
1701. }
1702. 

load_common_data Edit

1703. /* initialization common to all special levels */
1704. STATIC_OVL void
1705. load_common_data(fd, typ)
1706. dlb *fd;
1707. int typ;
1708. {
1709. 	uchar	n;
1710. 	long	lev_flags;
1711. 	int	i;
1712. 
1713.       {
1714. 	aligntyp atmp;
1715. 	/* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */
1716. 	i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
1717. 	if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
1718.       }
1719. 
1720. 	level.flags.is_maze_lev = typ == SP_LEV_MAZE;
1721. 
1722. 	/* Read the level initialization data */
1723. 	Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd);
1724. 	if(init_lev.init_present) {
1725. 	    if(init_lev.lit < 0)
1726. 		init_lev.lit = rn2(2);
1727. 	    mkmap(&init_lev);
1728. 	}
1729. 
1730. 	/* Read the per level flags */
1731. 	Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd);
1732. 	if (lev_flags & NOTELEPORT)
1733. 	    level.flags.noteleport = 1;
1734. 	if (lev_flags & HARDFLOOR)
1735. 	    level.flags.hardfloor = 1;
1736. 	if (lev_flags & NOMMAP)
1737. 	    level.flags.nommap = 1;
1738. 	if (lev_flags & SHORTSIGHTED)
1739. 	    level.flags.shortsighted = 1;
1740. 	if (lev_flags & ARBOREAL)
1741. 	    level.flags.arboreal = 1;
1742. 
1743. 	/* Read message */
1744. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
1745. 	if (n) {
1746. 	    lev_message = (char *) alloc(n + 1);
1747. 	    Fread((genericptr_t) lev_message, 1, (int) n, fd);
1748. 	    lev_message[n] = 0;
1749. 	}
1750. }
1751. 

load_one_monster Edit

1752. STATIC_OVL void
1753. load_one_monster(fd, m)
1754. dlb *fd;
1755. monster *m;
1756. {
1757. 	int size;
1758. 
1759. 	Fread((genericptr_t) m, 1, sizeof *m, fd);
1760. 	if ((size = m->name.len) != 0) {
1761. 	    m->name.str = (char *) alloc((unsigned)size + 1);
1762. 	    Fread((genericptr_t) m->name.str, 1, size, fd);
1763. 	    m->name.str[size] = '\0';
1764. 	} else
1765. 	    m->name.str = (char *) 0;
1766. 	if ((size = m->appear_as.len) != 0) {
1767. 	    m->appear_as.str = (char *) alloc((unsigned)size + 1);
1768. 	    Fread((genericptr_t) m->appear_as.str, 1, size, fd);
1769. 	    m->appear_as.str[size] = '\0';
1770. 	} else
1771. 	    m->appear_as.str = (char *) 0;
1772. }
1773. 

load_one_object Edit

1774. STATIC_OVL void
1775. load_one_object(fd, o)
1776. dlb *fd;
1777. object *o;
1778. {
1779. 	int size;
1780. 
1781. 	Fread((genericptr_t) o, 1, sizeof *o, fd);
1782. 	if ((size = o->name.len) != 0) {
1783. 	    o->name.str = (char *) alloc((unsigned)size + 1);
1784. 	    Fread((genericptr_t) o->name.str, 1, size, fd);
1785. 	    o->name.str[size] = '\0';
1786. 	} else
1787. 	    o->name.str = (char *) 0;
1788. }
1789. 

load_one_engraving Edit

1790. STATIC_OVL void
1791. load_one_engraving(fd, e)
1792. dlb *fd;
1793. engraving *e;
1794. {
1795. 	int size;
1796. 
1797. 	Fread((genericptr_t) e, 1, sizeof *e, fd);
1798. 	size = e->engr.len;
1799. 	e->engr.str = (char *) alloc((unsigned)size+1);
1800. 	Fread((genericptr_t) e->engr.str, 1, size, fd);
1801. 	e->engr.str[size] = '\0';
1802. }
1803. 

load_rooms Edit

1804. STATIC_OVL boolean
1805. load_rooms(fd)
1806. dlb *fd;
1807. {
1808. 	xchar		nrooms, ncorr;
1809. 	char		n;
1810. 	short		size;
1811. 	corridor	tmpcor;
1812. 	room**		tmproom;
1813. 	int		i, j;
1814. 
1815. 	load_common_data(fd, SP_LEV_ROOMS);
1816. 
1817. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */
1818. 	if (n) {
1819. 		Fread((genericptr_t)robjects, sizeof(*robjects), n, fd);
1820. 		sp_lev_shuffle(robjects, (char *)0, (int)n);
1821. 	}
1822. 
1823. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */
1824. 	if (n) {
1825. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd);
1826. 		sp_lev_shuffle(rmonst, (char *)0, (int)n);
1827. 	}
1828. 
1829. 	Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd);
1830. 						/* Number of rooms to read */
1831. 	tmproom = NewTab(room,nrooms);
1832. 	for (i=0;i<nrooms;i++) {
1833. 		room *r;
1834. 
1835. 		r = tmproom[i] = New(room);
1836. 
1837. 		/* Let's see if this room has a name */
1838. 		Fread((genericptr_t) &size, 1, sizeof(size), fd);
1839. 		if (size > 0) {	/* Yup, it does! */
1840. 			r->name = (char *) alloc((unsigned)size + 1);
1841. 			Fread((genericptr_t) r->name, 1, size, fd);
1842. 			r->name[size] = 0;
1843. 		} else
1844. 		    r->name = (char *) 0;
1845. 
1846. 		/* Let's see if this room has a parent */
1847. 		Fread((genericptr_t) &size, 1, sizeof(size), fd);
1848. 		if (size > 0) {	/* Yup, it does! */
1849. 			r->parent = (char *) alloc((unsigned)size + 1);
1850. 			Fread((genericptr_t) r->parent, 1, size, fd);
1851. 			r->parent[size] = 0;
1852. 		} else
1853. 		    r->parent = (char *) 0;
1854. 
1855. 		Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd);
1856. 					/* x pos on the grid (1-5) */
1857. 		Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd);
1858. 					 /* y pos on the grid (1-5) */
1859. 		Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd);
1860. 					 /* width of the room */
1861. 		Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd);
1862. 					 /* height of the room */
1863. 		Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd);
1864. 					 /* horizontal alignment */
1865. 		Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd);
1866. 					 /* vertical alignment */
1867. 		Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd);
1868. 					 /* type of room (zoo, shop, etc.) */
1869. 		Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd);
1870. 					 /* chance of room being special. */
1871. 		Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd);
1872. 					 /* lit or not ? */
1873. 		Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd);
1874. 					 /* to be filled? */
1875. 		r->nsubroom= 0;
1876. 
1877. 		/* read the doors */
1878. 		Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd);
1879. 		if ((n = r->ndoor) != 0)
1880. 		    r->doors = NewTab(room_door, n);
1881. 		while(n--) {
1882. 			r->doors[(int)n] = New(room_door);
1883. 			Fread((genericptr_t) r->doors[(int)n], 1,
1884. 				sizeof(room_door), fd);
1885. 		}
1886. 
1887. 		/* read the stairs */
1888. 		Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd);
1889. 		if ((n = r->nstair) != 0)
1890. 		    r->stairs = NewTab(stair, n);
1891. 		while (n--) {
1892. 			r->stairs[(int)n] = New(stair);
1893. 			Fread((genericptr_t) r->stairs[(int)n], 1,
1894. 				sizeof(stair), fd);
1895. 		}
1896. 
1897. 		/* read the altars */
1898. 		Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd);
1899. 		if ((n = r->naltar) != 0)
1900. 		    r->altars = NewTab(altar, n);
1901. 		while (n--) {
1902. 			r->altars[(int)n] = New(altar);
1903. 			Fread((genericptr_t) r->altars[(int)n], 1,
1904. 				sizeof(altar), fd);
1905. 		}
1906. 
1907. 		/* read the fountains */
1908. 		Fread((genericptr_t) &r->nfountain, 1,
1909. 			sizeof(r->nfountain), fd);
1910. 		if ((n = r->nfountain) != 0)
1911. 		    r->fountains = NewTab(fountain, n);
1912. 		while (n--) {
1913. 			r->fountains[(int)n] = New(fountain);
1914. 			Fread((genericptr_t) r->fountains[(int)n], 1,
1915. 				sizeof(fountain), fd);
1916. 		}
1917. 
1918. 		/* read the sinks */
1919. 		Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd);
1920. 		if ((n = r->nsink) != 0)
1921. 		    r->sinks = NewTab(sink, n);
1922. 		while (n--) {
1923. 			r->sinks[(int)n] = New(sink);
1924. 			Fread((genericptr_t) r->sinks[(int)n], 1, sizeof(sink), fd);
1925. 		}
1926. 
1927. 		/* read the pools */
1928. 		Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd);
1929. 		if ((n = r->npool) != 0)
1930. 		    r->pools = NewTab(pool,n);
1931. 		while (n--) {
1932. 			r->pools[(int)n] = New(pool);
1933. 			Fread((genericptr_t) r->pools[(int)n], 1, sizeof(pool), fd);
1934. 		}
1935. 
1936. 		/* read the traps */
1937. 		Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd);
1938. 		if ((n = r->ntrap) != 0)
1939. 		    r->traps = NewTab(trap, n);
1940. 		while(n--) {
1941. 			r->traps[(int)n] = New(trap);
1942. 			Fread((genericptr_t) r->traps[(int)n], 1, sizeof(trap), fd);
1943. 		}
1944. 
1945. 		/* read the monsters */
1946. 		Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd);
1947. 		if ((n = r->nmonster) != 0) {
1948. 		    r->monsters = NewTab(monster, n);
1949. 		    while(n--) {
1950. 			r->monsters[(int)n] = New(monster);
1951. 			load_one_monster(fd, r->monsters[(int)n]);
1952. 		    }
1953. 		} else
1954. 		    r->monsters = 0;
1955. 
1956. 		/* read the objects, in same order as mazes */
1957. 		Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd);
1958. 		if ((n = r->nobject) != 0) {
1959. 		    r->objects = NewTab(object, n);
1960. 		    for (j = 0; j < n; ++j) {
1961. 			r->objects[j] = New(object);
1962. 			load_one_object(fd, r->objects[j]);
1963. 		    }
1964. 		} else
1965. 		    r->objects = 0;
1966. 
1967. 		/* read the gold piles */
1968. 		Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd);
1969. 		if ((n = r->ngold) != 0)
1970. 		    r->golds = NewTab(gold, n);
1971. 		while (n--) {
1972. 			r->golds[(int)n] = New(gold);
1973. 			Fread((genericptr_t) r->golds[(int)n], 1, sizeof(gold), fd);
1974. 		}
1975. 
1976. 		/* read the engravings */
1977. 		Fread((genericptr_t) &r->nengraving, 1,
1978. 			sizeof(r->nengraving), fd);
1979. 		if ((n = r->nengraving) != 0) {
1980. 		    r->engravings = NewTab(engraving,n);
1981. 		    while (n--) {
1982. 			r->engravings[(int)n] = New(engraving);
1983. 			load_one_engraving(fd, r->engravings[(int)n]);
1984. 		    }
1985. 		} else
1986. 		    r->engravings = 0;
1987. 
1988. 	}
1989. 
1990. 	/* Now that we have loaded all the rooms, search the
1991. 	 * subrooms and create the links.
1992. 	 */
1993. 
1994. 	for (i = 0; i<nrooms; i++)
1995. 	    if (tmproom[i]->parent) {
1996. 		    /* Search the parent room */
1997. 		    for(j=0; j<nrooms; j++)
1998. 			if (tmproom[j]->name && !strcmp(tmproom[j]->name,
1999. 						       tmproom[i]->parent)) {
2000. 				n = tmproom[j]->nsubroom++;
2001. 				tmproom[j]->subrooms[(int)n] = tmproom[i];
2002. 				break;
2003. 			}
2004. 	    }
2005. 
2006. 	/*
2007. 	 * Create the rooms now...
2008. 	 */
2009. 
2010. 	for (i=0; i < nrooms; i++)
2011. 	    if(!tmproom[i]->parent)
2012. 		build_room(tmproom[i], (room *) 0);
2013. 
2014. 	free_rooms(tmproom, nrooms);
2015. 
2016. 	/* read the corridors */
2017. 
2018. 	Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd);
2019. 	for (i=0; i<ncorr; i++) {
2020. 		Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd);
2021. 		create_corridor(&tmpcor);
2022. 	}
2023. 
2024. 	return TRUE;
2025. }
2026. 

maze1xy Edit

2027. /*
2028.  * Select a random coordinate in the maze.
2029.  *
2030.  * We want a place not 'touched' by the loader.  That is, a place in
2031.  * the maze outside every part of the special level.
2032.  */
2033. 
2034. STATIC_OVL void
2035. maze1xy(m, humidity)
2036. coord *m;
2037. int humidity;
2038. {
2039. 	register int x, y, tryct = 2000;
2040. 	/* tryct:  normally it won't take more than ten or so tries due
2041. 	   to the circumstances under which we'll be called, but the
2042. 	   `humidity' screening might drastically change the chances */
2043. 
2044. 	do {
2045. 	    x = rn1(x_maze_max - 3, 3);
2046. 	    y = rn1(y_maze_max - 3, 3);
2047. 	    if (--tryct < 0) break;	/* give up */
2048. 	} while (!(x % 2) || !(y % 2) || Map[x][y] ||
2049. 		 !is_ok_location((schar)x, (schar)y, humidity));
2050. 
2051. 	m->x = (xchar)x,  m->y = (xchar)y;
2052. }
2053. 

load_maze Edit

2054. /*
2055.  * The Big Thing: special maze loader
2056.  *
2057.  * Could be cleaner, but it works.
2058.  */
2059. 
2060. STATIC_OVL boolean
2061. load_maze(fd)
2062. dlb *fd;
2063. {
2064.     xchar   x, y, typ;
2065.     boolean prefilled, room_not_needed;
2066. 
2067.     char    n, numpart = 0;
2068.     xchar   nwalk = 0, nwalk_sav;
2069.     schar   filling;
2070.     char    halign, valign;
2071. 
2072.     int     xi, dir, size;
2073.     coord   mm;
2074.     int     mapcount, mapcountmax, mapfact;
2075. 
2076.     lev_region  tmplregion;
2077.     region  tmpregion;
2078.     door    tmpdoor;
2079.     trap    tmptrap;
2080.     monster tmpmons;
2081.     object  tmpobj;
2082.     drawbridge tmpdb;
2083.     walk    tmpwalk;
2084.     digpos  tmpdig;
2085.     lad     tmplad;
2086.     stair   tmpstair, prevstair;
2087.     altar   tmpaltar;
2088.     gold    tmpgold;
2089.     fountain tmpfountain;
2090.     engraving tmpengraving;
2091.     xchar   mustfill[(MAXNROFROOMS+1)*2];
2092.     struct trap *badtrap;
2093.     boolean has_bounds;
2094. 
2095.     (void) memset((genericptr_t)&Map[0][0], 0, sizeof Map);
2096.     load_common_data(fd, SP_LEV_MAZE);
2097. 
2098.     /* Initialize map */
2099.     Fread((genericptr_t) &filling, 1, sizeof(filling), fd);
2100.     if (!init_lev.init_present) { /* don't init if mkmap() has been called */
2101.       for(x = 2; x <= x_maze_max; x++)
2102. 	for(y = 0; y <= y_maze_max; y++)
2103. 	    if (filling == -1) {
2104. #ifndef WALLIFIED_MAZE
2105. 		    levl[x][y].typ = STONE;
2106. #else
2107. 		    levl[x][y].typ =
2108. 			(y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL;
2109. #endif
2110. 	    } else {
2111. 		    levl[x][y].typ = filling;
2112. 	    }
2113.     }
2114. 
2115.     /* Start reading the file */
2116.     Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
2117. 						/* Number of parts */
2118.     if (!numpart || numpart > 9)
2119. 	panic("load_maze error: numpart = %d", (int) numpart);
2120. 
2121.     while (numpart--) {
2122. 	Fread((genericptr_t) &halign, 1, sizeof(halign), fd);
2123. 					/* Horizontal alignment */
2124. 	Fread((genericptr_t) &valign, 1, sizeof(valign), fd);
2125. 					/* Vertical alignment */
2126. 	Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd);
2127. 					/* size in X */
2128. 	Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd);
2129. 					/* size in Y */
2130. 	switch((int) halign) {
2131. 	    case LEFT:	    xstart = 3;					break;
2132. 	    case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);	break;
2133. 	    case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break;
2134. 	    case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);	break;
2135. 	    case RIGHT:     xstart = x_maze_max-xsize-1;		break;
2136. 	}
2137. 	switch((int) valign) {
2138. 	    case TOP:	    ystart = 3;					break;
2139. 	    case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break;
2140. 	    case BOTTOM:    ystart = y_maze_max-ysize-1;		break;
2141. 	}
2142. 	if (!(xstart % 2)) xstart++;
2143. 	if (!(ystart % 2)) ystart++;
2144. 	if ((ystart < 0) || (ystart + ysize > ROWNO)) {
2145. 	    /* try to move the start a bit */
2146. 	    ystart += (ystart > 0) ? -2 : 2;
2147. 	    if(ysize == ROWNO) ystart = 0;
2148. 	    if(ystart < 0 || ystart + ysize > ROWNO)
2149. 		panic("reading special level with ysize too large");
2150. 	}
2151. 
2152. 	/*
2153. 	 * If any CROSSWALLs are found, must change to ROOM after REGION's
2154. 	 * are laid out.  CROSSWALLS are used to specify "invisible"
2155. 	 * boundaries where DOOR syms look bad or aren't desirable.
2156. 	 */
2157. 	has_bounds = FALSE;
2158. 
2159. 	if(init_lev.init_present && xsize <= 1 && ysize <= 1) {
2160. 	    xstart = 1;
2161. 	    ystart = 0;
2162. 	    xsize = COLNO-1;
2163. 	    ysize = ROWNO;
2164. 	} else {
2165. 	    /* Load the map */
2166. 	    for(y = ystart; y < ystart+ysize; y++)
2167. 		for(x = xstart; x < xstart+xsize; x++) {
2168. 		    levl[x][y].typ = Fgetc(fd);
2169. 		    levl[x][y].lit = FALSE;
2170. 		    /* clear out levl: load_common_data may set them */
2171. 		    levl[x][y].flags = 0;
2172. 		    levl[x][y].horizontal = 0;
2173. 		    levl[x][y].roomno = 0;
2174. 		    levl[x][y].edge = 0;
2175. 		    /*
2176. 		     * Note: Even though levl[x][y].typ is type schar,
2177. 		     *	 lev_comp.y saves it as type char. Since schar != char
2178. 		     *	 all the time we must make this exception or hack
2179. 		     *	 through lev_comp.y to fix.
2180. 		     */
2181. 
2182. 		    /*
2183. 		     *  Set secret doors to closed (why not trapped too?).  Set
2184. 		     *  the horizontal bit.
2185. 		     */
2186. 		    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
2187. 			if(levl[x][y].typ == SDOOR)
2188. 			    levl[x][y].doormask = D_CLOSED;
2189. 			/*
2190. 			 *  If there is a wall to the left that connects to a
2191. 			 *  (secret) door, then it is horizontal.  This does
2192. 			 *  not allow (secret) doors to be corners of rooms.
2193. 			 */
2194. 			if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
2195. 					    levl[x-1][y].horizontal))
2196. 			    levl[x][y].horizontal = 1;
2197. 		    } else if(levl[x][y].typ == HWALL ||
2198. 				levl[x][y].typ == IRONBARS)
2199. 			levl[x][y].horizontal = 1;
2200. 		    else if(levl[x][y].typ == LAVAPOOL)
2201. 			levl[x][y].lit = 1;
2202. 		    else if(levl[x][y].typ == CROSSWALL)
2203. 			has_bounds = TRUE;
2204. 		    Map[x][y] = 1;
2205. 		}
2206. 	    if (init_lev.init_present && init_lev.joined)
2207. 		remove_rooms(xstart, ystart, xstart+xsize, ystart+ysize);
2208. 	}
2209. 
2210. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2211. 						/* Number of level regions */
2212. 	if(n) {
2213. 	    if(num_lregions) {
2214. 		/* realloc the lregion space to add the new ones */
2215. 		/* don't really free it up until the whole level is done */
2216. 		lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
2217. 						(unsigned)(n+num_lregions));
2218. 		(void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions,
2219. 					sizeof(lev_region) * num_lregions);
2220. 		Free(lregions);
2221. 		num_lregions += n;
2222. 		lregions = newl;
2223. 	    } else {
2224. 		num_lregions = n;
2225. 		lregions = (lev_region *)
2226. 				alloc(sizeof(lev_region) * (unsigned)n);
2227. 	    }
2228. 	}
2229. 
2230. 	while(n--) {
2231. 	    Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd);
2232. 	    if ((size = tmplregion.rname.len) != 0) {
2233. 		tmplregion.rname.str = (char *) alloc((unsigned)size + 1);
2234. 		Fread((genericptr_t) tmplregion.rname.str, size, 1, fd);
2235. 		tmplregion.rname.str[size] = '\0';
2236. 	    } else
2237. 		tmplregion.rname.str = (char *) 0;
2238. 	    if(!tmplregion.in_islev) {
2239. 		get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1,
2240. 								DRY|WET);
2241. 		get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2,
2242. 								DRY|WET);
2243. 	    }
2244. 	    if(!tmplregion.del_islev) {
2245. 		get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1,
2246. 								DRY|WET);
2247. 		get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2,
2248. 								DRY|WET);
2249. 	    }
2250. 	    lregions[(int)n] = tmplregion;
2251. 	}
2252. 
2253. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2254. 						/* Random objects */
2255. 	if(n) {
2256. 		Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd);
2257. 		sp_lev_shuffle(robjects, (char *)0, (int)n);
2258. 	}
2259. 
2260. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2261. 						/* Random locations */
2262. 	if(n) {
2263. 		Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd);
2264. 		Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd);
2265. 		sp_lev_shuffle(rloc_x, rloc_y, (int)n);
2266. 	}
2267. 
2268. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2269. 						/* Random monsters */
2270. 	if(n) {
2271. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd);
2272. 		sp_lev_shuffle(rmonst, (char *)0, (int)n);
2273. 	}
2274. 
2275. 	(void) memset((genericptr_t)mustfill, 0, sizeof(mustfill));
2276. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2277. 						/* Number of subrooms */
2278. 	while(n--) {
2279. 		register struct mkroom *troom;
2280. 
2281. 		Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd);
2282. 
2283. 		if(tmpregion.rtype > MAXRTYPE) {
2284. 		    tmpregion.rtype -= MAXRTYPE+1;
2285. 		    prefilled = TRUE;
2286. 		} else
2287. 		    prefilled = FALSE;
2288. 
2289. 		if(tmpregion.rlit < 0)
2290. 		    tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
2291. 			? TRUE : FALSE;
2292. 
2293. 		get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET);
2294. 		get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET);
2295. 
2296. 		/* for an ordinary room, `prefilled' is a flag to force
2297. 		   an actual room to be created (such rooms are used to
2298. 		   control placement of migrating monster arrivals) */
2299. 		room_not_needed = (tmpregion.rtype == OROOM &&
2300. 				   !tmpregion.rirreg && !prefilled);
2301. 		if (room_not_needed || nroom >= MAXNROFROOMS) {
2302. 		    if (!room_not_needed)
2303. 			impossible("Too many rooms on new level!");
2304. 		    light_region(&tmpregion);
2305. 		    continue;
2306. 		}
2307. 
2308. 		troom = &rooms[nroom];
2309. 
2310. 		/* mark rooms that must be filled, but do it later */
2311. 		if (tmpregion.rtype != OROOM)
2312. 		    mustfill[nroom] = (prefilled ? 2 : 1);
2313. 
2314. 		if(tmpregion.rirreg) {
2315. 		    min_rx = max_rx = tmpregion.x1;
2316. 		    min_ry = max_ry = tmpregion.y1;
2317. 		    flood_fill_rm(tmpregion.x1, tmpregion.y1,
2318. 				  nroom+ROOMOFFSET, tmpregion.rlit, TRUE);
2319. 		    add_room(min_rx, min_ry, max_rx, max_ry,
2320. 			     FALSE, tmpregion.rtype, TRUE);
2321. 		    troom->rlit = tmpregion.rlit;
2322. 		    troom->irregular = TRUE;
2323. 		} else {
2324. 		    add_room(tmpregion.x1, tmpregion.y1,
2325. 			     tmpregion.x2, tmpregion.y2,
2326. 			     tmpregion.rlit, tmpregion.rtype, TRUE);
2327. #ifdef SPECIALIZATION
2328. 		    topologize(troom,FALSE);		/* set roomno */
2329. #else
2330. 		    topologize(troom);			/* set roomno */
2331. #endif
2332. 		}
2333. 	}
2334. 
2335. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2336. 						/* Number of doors */
2337. 	while(n--) {
2338. 		struct mkroom *croom = &rooms[0];
2339. 
2340. 		Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd);
2341. 
2342. 		x = tmpdoor.x;	y = tmpdoor.y;
2343. 		typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
2344. 
2345. 		get_location(&x, &y, DRY);
2346. 		if(levl[x][y].typ != SDOOR)
2347. 			levl[x][y].typ = DOOR;
2348. 		else {
2349. 			if(typ < D_CLOSED)
2350. 			    typ = D_CLOSED; /* force it to be closed */
2351. 		}
2352. 		levl[x][y].doormask = typ;
2353. 
2354. 		/* Now the complicated part, list it with each subroom */
2355. 		/* The dog move and mail daemon routines use this */
2356. 		while(croom->hx >= 0 && doorindex < DOORMAX) {
2357. 		    if(croom->hx >= x-1 && croom->lx <= x+1 &&
2358. 		       croom->hy >= y-1 && croom->ly <= y+1) {
2359. 			/* Found it */
2360. 			add_door(x, y, croom);
2361. 		    }
2362. 		    croom++;
2363. 		}
2364. 	}
2365. 
2366. 	/* now that we have rooms _and_ associated doors, fill the rooms */
2367. 	for(n = 0; n < SIZE(mustfill); n++)
2368. 	    if(mustfill[(int)n])
2369. 		fill_room(&rooms[(int)n], (mustfill[(int)n] == 2));
2370. 
2371. 	/* if special boundary syms (CROSSWALL) in map, remove them now */
2372. 	if(has_bounds) {
2373. 	    for(x = xstart; x < xstart+xsize; x++)
2374. 		for(y = ystart; y < ystart+ysize; y++)
2375. 		    if(levl[x][y].typ == CROSSWALL)
2376. 			levl[x][y].typ = ROOM;
2377. 	}
2378. 
2379. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2380. 						/* Number of drawbridges */
2381. 	while(n--) {
2382. 		Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd);
2383. 
2384. 		x = tmpdb.x;  y = tmpdb.y;
2385. 		get_location(&x, &y, DRY|WET);
2386. 
2387. 		if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open))
2388. 		    impossible("Cannot create drawbridge.");
2389. 	}
2390. 
2391. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2392. 						/* Number of mazewalks */
2393. 	while(n--) {
2394. 		Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd);
2395. 
2396. 		get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET);
2397. 
2398. 		walklist[nwalk++] = tmpwalk;
2399. 	}
2400. 
2401. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2402. 						/* Number of non_diggables */
2403. 	while(n--) {
2404. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
2405. 
2406. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
2407. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
2408. 
2409. 		set_wall_property(tmpdig.x1, tmpdig.y1,
2410. 				  tmpdig.x2, tmpdig.y2, W_NONDIGGABLE);
2411. 	}
2412. 
2413. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2414. 						/* Number of non_passables */
2415. 	while(n--) {
2416. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
2417. 
2418. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
2419. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
2420. 
2421. 		set_wall_property(tmpdig.x1, tmpdig.y1,
2422. 				  tmpdig.x2, tmpdig.y2, W_NONPASSWALL);
2423. 	}
2424. 
2425. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2426. 						/* Number of ladders */
2427. 	while(n--) {
2428. 		Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd);
2429. 
2430. 		x = tmplad.x;  y = tmplad.y;
2431. 		get_location(&x, &y, DRY);
2432. 
2433. 		levl[x][y].typ = LADDER;
2434. 		if (tmplad.up == 1) {
2435. 			xupladder = x;	yupladder = y;
2436. 			levl[x][y].ladder = LA_UP;
2437. 		} else {
2438. 			xdnladder = x;	ydnladder = y;
2439. 			levl[x][y].ladder = LA_DOWN;
2440. 		}
2441. 	}
2442. 
2443. 	prevstair.x = prevstair.y = 0;
2444. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2445. 						/* Number of stairs */
2446. 	while(n--) {
2447. 		Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd);
2448. 
2449. 		xi = 0;
2450. 		do {
2451. 		    x = tmpstair.x;  y = tmpstair.y;
2452. 		    get_location(&x, &y, DRY);
2453. 		} while(prevstair.x && xi++ < 100 &&
2454. 			distmin(x,y,prevstair.x,prevstair.y) <= 8);
2455. 		if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
2456. 		mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0);
2457. 		prevstair.x = x;
2458. 		prevstair.y = y;
2459. 	}
2460. 
2461. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2462. 						/* Number of altars */
2463. 	while(n--) {
2464. 		Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd);
2465. 
2466. 		create_altar(&tmpaltar, (struct mkroom *)0);
2467. 	}
2468. 
2469. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2470. 						/* Number of fountains */
2471. 	while (n--) {
2472. 		Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd);
2473. 
2474. 		create_feature(tmpfountain.x, tmpfountain.y,
2475. 			       (struct mkroom *)0, FOUNTAIN);
2476. 	}
2477. 
2478. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2479. 						/* Number of traps */
2480. 	while(n--) {
2481. 		Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd);
2482. 
2483. 		create_trap(&tmptrap, (struct mkroom *)0);
2484. 	}
2485. 
2486. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2487. 						/* Number of monsters */
2488. 	while(n--) {
2489. 		load_one_monster(fd, &tmpmons);
2490. 
2491. 		create_monster(&tmpmons, (struct mkroom *)0);
2492. 	}
2493. 
2494. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2495. 						/* Number of objects */
2496. 	while(n--) {
2497. 		load_one_object(fd, &tmpobj);
2498. 
2499. 		create_object(&tmpobj, (struct mkroom *)0);
2500. 	}
2501. 
2502. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2503. 						/* Number of gold piles */
2504. 	while (n--) {
2505. 		Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd);
2506. 
2507. 		create_gold(&tmpgold, (struct mkroom *)0);
2508. 	}
2509. 
2510. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2511. 						/* Number of engravings */
2512. 	while(n--) {
2513. 		load_one_engraving(fd, &tmpengraving);
2514. 
2515. 		create_engraving(&tmpengraving, (struct mkroom *)0);
2516. 	}
2517. 
2518.     }		/* numpart loop */
2519. 
2520.     nwalk_sav = nwalk;
2521.     while(nwalk--) {
2522. 	    x = (xchar) walklist[nwalk].x;
2523. 	    y = (xchar) walklist[nwalk].y;
2524. 	    dir = walklist[nwalk].dir;
2525. 
2526. 	    /* don't use move() - it doesn't use W_NORTH, etc. */
2527. 	    switch (dir) {
2528. 		case W_NORTH: --y; break;
2529. 		case W_SOUTH: y++; break;
2530. 		case W_EAST:  x++; break;
2531. 		case W_WEST:  --x; break;
2532. 		default: panic("load_maze: bad MAZEWALK direction");
2533. 	    }
2534. 
2535. 	    if(!IS_DOOR(levl[x][y].typ)) {
2536. #ifndef WALLIFIED_MAZE
2537. 		levl[x][y].typ = CORR;
2538. #else
2539. 		levl[x][y].typ = ROOM;
2540. #endif
2541. 		levl[x][y].flags = 0;
2542. 	    }
2543. 
2544. 	    /*
2545. 	     * We must be sure that the parity of the coordinates for
2546. 	     * walkfrom() is odd.  But we must also take into account
2547. 	     * what direction was chosen.
2548. 	     */
2549. 	    if(!(x % 2)) {
2550. 		if (dir == W_EAST)
2551. 		    x++;
2552. 		else
2553. 		    x--;
2554. 
2555. 		/* no need for IS_DOOR check; out of map bounds */
2556. #ifndef WALLIFIED_MAZE
2557. 		levl[x][y].typ = CORR;
2558. #else
2559. 		levl[x][y].typ = ROOM;
2560. #endif
2561. 		levl[x][y].flags = 0;
2562. 	    }
2563. 
2564. 	    if (!(y % 2)) {
2565. 		if (dir == W_SOUTH)
2566. 		    y++;
2567. 		else
2568. 		    y--;
2569. 	    }
2570. 
2571. 	    walkfrom(x, y);
2572.     }
2573.     wallification(1, 0, COLNO-1, ROWNO-1);
2574. 
2575.     /*
2576.      * If there's a significant portion of maze unused by the special level,
2577.      * we don't want it empty.
2578.      *
2579.      * Makes the number of traps, monsters, etc. proportional
2580.      * to the size of the maze.
2581.      */
2582.     mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
2583. 
2584.     for(x = 2; x < x_maze_max; x++)
2585. 	for(y = 0; y < y_maze_max; y++)
2586. 	    if(Map[x][y]) mapcount--;
2587. 
2588.     if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) {
2589. 	    mapfact = (int) ((mapcount * 100L) / mapcountmax);
2590. 	    for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
2591. 		    maze1xy(&mm, DRY);
2592. 		    (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
2593. 							mm.x, mm.y, TRUE);
2594. 	    }
2595. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
2596. 		    maze1xy(&mm, DRY);
2597. 		    (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE);
2598. 	    }
2599. 	    for (x = rn2(2); x; x--) {
2600. 		maze1xy(&mm, DRY);
2601. 		(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS);
2602. 	    }
2603. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
2604. 		    maze1xy(&mm, WET|DRY);
2605. 		    (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS);
2606. 	    }
2607. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
2608. 		    maze1xy(&mm, DRY);
2609. 		    (void) mkgold(0L,mm.x,mm.y);
2610. 	    }
2611. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
2612. 		    int trytrap;
2613. 
2614. 		    maze1xy(&mm, DRY);
2615. 		    trytrap = rndtrap();
2616. 		    if (sobj_at(BOULDER, mm.x, mm.y))
2617. 			while (trytrap == PIT || trytrap == SPIKED_PIT ||
2618. 				trytrap == TRAPDOOR || trytrap == HOLE)
2619. 			    trytrap = rndtrap();
2620. 		    (void) maketrap(mm.x, mm.y, trytrap);
2621. 	    }
2622.     }
2623.     return TRUE;
2624. }
2625. 

load_special Edit

2626. /*
2627.  * General loader
2628.  */
2629. 
2630. boolean
2631. load_special(name)
2632. const char *name;
2633. {
2634. 	dlb *fd;
2635. 	boolean result = FALSE;
2636. 	char c;
2637. 	struct version_info vers_info;
2638. 
2639. 	fd = dlb_fopen(name, RDBMODE);
2640. 	if (!fd) return FALSE;
2641. 
2642. 	Fread((genericptr_t) &vers_info, sizeof vers_info, 1, fd);
2643. 	if (!check_version(&vers_info, name, TRUE))
2644. 	    goto give_up;
2645. 
2646. 	Fread((genericptr_t) &c, sizeof c, 1, fd); /* c Header */
2647. 
2648. 	switch (c) {
2649. 		case SP_LEV_ROOMS:
2650. 		    result = load_rooms(fd);
2651. 		    break;
2652. 		case SP_LEV_MAZE:
2653. 		    result = load_maze(fd);
2654. 		    break;
2655. 		default:	/* ??? */
2656. 		    result = FALSE;
2657. 	}
2658.  give_up:
2659. 	(void)dlb_fclose(fd);
2660. 	return result;
2661. }
2662. 
2663. /*sp_lev.c*/

Around Wikia's network

Random Wiki