xref: /dragonfly/games/hack/hack.mklev.c (revision 0ca59c34)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.mklev.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.mklev.c,v 1.6 1999/11/16 10:26:36 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.mklev.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */
5 
6 #include "hack.h"
7 
8 #define	somex()	((random()%(croom->hx-croom->lx+1))+croom->lx)
9 #define	somey()	((random()%(croom->hy-croom->ly+1))+croom->ly)
10 
11 #define	XLIM	4	/* define minimum required space around a room */
12 #define	YLIM	3
13 boolean secret;		/* TRUE while making a vault: increase [XY]LIM */
14 struct mkroom rooms[MAXNROFROOMS+1];
15 int smeq[MAXNROFROOMS+1];
16 coord doors[DOORMAX];
17 int doorindex;
18 struct rm zerorm;
19 schar nxcor;
20 boolean goldseen;
21 int nroom;
22 xchar xdnstair, xupstair, ydnstair, yupstair;
23 
24 /* Definitions used by makerooms() and addrs() */
25 #define	MAXRS	50	/* max lth of temp rectangle table - arbitrary */
26 struct rectangle {
27 	xchar rlx, rly, rhx, rhy;
28 } rs[MAXRS + 1];
29 int rscnt, rsmax;	/* 0..rscnt-1: currently under consideration */
30 			/* rscnt..rsmax: discarded */
31 
32 static bool makerooms(void);
33 static void addrs(int, int, int, int);
34 static void addrsx(int, int, int, int, bool);
35 static int comp(const void *, const void *);
36 static coord finddpos(int, int, int, int);
37 static bool okdoor(int, int);
38 static void dodoor(int, int, struct mkroom *);
39 static void dosdoor(int, int, struct mkroom *, int);
40 static bool maker(schar, schar, schar, schar);
41 static void makecorridors(void);
42 static void join(int, int);
43 static void make_niches(void);
44 static void makevtele(void);
45 static void makeniche(bool);
46 
47 void
48 makelevel(void)
49 {
50 	struct mkroom *croom, *troom;
51 	unsigned tryct;
52 	int x, y;
53 
54 	nroom = 0;
55 	doorindex = 0;
56 	rooms[0].hx = -1;	/* in case we are in a maze */
57 
58 	for (x = 0; x < COLNO; x++)
59 		for (y = 0; y < ROWNO; y++)
60 			levl[x][y] = zerorm;
61 
62 	oinit();		/* assign level dependent obj probabilities */
63 
64 	if (dlevel >= rn1(3, 26)) {	/* there might be several mazes */
65 		makemaz();
66 		return;
67 	}
68 
69 	/* construct the rooms */
70 	nroom = 0;
71 	secret = FALSE;
72 	makerooms();
73 
74 	/* construct stairs (up and down in different rooms if possible) */
75 	croom = &rooms[rn2(nroom)];
76 	xdnstair = somex();
77 	ydnstair = somey();
78 	levl[xdnstair][ydnstair].scrsym = '>';
79 	levl[xdnstair][ydnstair].typ = STAIRS;
80 	if (nroom > 1) {
81 		troom = croom;
82 		croom = &rooms[rn2(nroom - 1)];
83 		if (croom >= troom)
84 			croom++;
85 	}
86 	xupstair = somex();	/* %% < and > might be in the same place */
87 	yupstair = somey();
88 	levl[xupstair][yupstair].scrsym = '<';
89 	levl[xupstair][yupstair].typ = STAIRS;
90 
91 	/* for each room: put things inside */
92 	for (croom = rooms; croom->hx > 0; croom++) {
93 		/* put a sleeping monster inside */
94 		/*
95 		 * Note: monster may be on the stairs. This cannot be
96 		 * avoided: maybe the player fell through a trapdoor while a
97 		 * monster was on the stairs. Conclusion: we have to check
98 		 * for monsters on the stairs anyway.
99 		 */
100 		if (!rn2(3))
101 			makemon(NULL, somex(), somey());
102 
103 		/* put traps and mimics inside */
104 		goldseen = FALSE;
105 		while (!rn2(8 - (dlevel / 6)))
106 			mktrap(0, 0, croom);
107 		if (!goldseen && !rn2(3))
108 			mkgold(0L, somex(), somey());
109 		if (!rn2(3)) {
110 			mkobj_at(0, somex(), somey());
111 			tryct = 0;
112 			while (!rn2(5)) {
113 				if (++tryct > 100) {
114 					printf("tryct overflow4\n");
115 					break;
116 				}
117 				mkobj_at(0, somex(), somey());
118 			}
119 		}
120 	}
121 
122 	qsort((char *)rooms, nroom, sizeof(struct mkroom), comp);
123 	makecorridors();
124 	make_niches();
125 
126 	/* make a secret treasure vault, not connected to the rest */
127 	if (nroom <= (2 * MAXNROFROOMS / 3))
128 		if (rn2(3)) {
129 			troom = &rooms[nroom];
130 			secret = TRUE;
131 			if (makerooms()) {
132 				troom->rtype = VAULT;	/* treasure vault */
133 				for (x = troom->lx; x <= troom->hx; x++)
134 					for (y = troom->ly; y <= troom->hy; y++)
135 						mkgold((long)(rnd(dlevel *
136 						    100) + 50), x, y);
137 				if (!rn2(3))
138 					makevtele();
139 			}
140 		}
141 
142 #ifndef QUEST
143 #ifdef WIZARD
144 	if (wizard && getenv("SHOPTYPE"))
145 		mkshop();
146 	else
147 #endif /* WIZARD */
148 	if (dlevel > 1 && dlevel < 20 && rn2(dlevel) < 3)
149 		mkshop();
150 	else if (dlevel > 6 && !rn2(7))
151 		mkzoo(ZOO);
152 	else if (dlevel > 9 && !rn2(5))
153 		mkzoo(BEEHIVE);
154 	else if (dlevel > 11 && !rn2(6))
155 		mkzoo(MORGUE);
156 	else if (dlevel > 18 && !rn2(6))
157 		mkswamp();
158 #endif /* QUEST */
159 }
160 
161 static bool
162 makerooms(void)
163 {
164 	struct rectangle *rsp;
165 	int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy;
166 	int tryct = 0, xlim, ylim;
167 
168 	/* init */
169 	xlim = XLIM + secret;
170 	ylim = YLIM + secret;
171 	if (nroom == 0) {
172 		rsp = rs;
173 		rsp->rlx = rsp->rly = 0;
174 		rsp->rhx = COLNO - 1;
175 		rsp->rhy = ROWNO - 1;
176 		rsmax = 1;
177 	}
178 	rscnt = rsmax;
179 
180 	/* make rooms until satisfied */
181 	while (rscnt > 0 && nroom < MAXNROFROOMS - 1) {
182 		if (!secret && nroom > (MAXNROFROOMS / 3) &&
183 		    !rn2((MAXNROFROOMS - nroom) * (MAXNROFROOMS - nroom)))
184 			return (0);
185 
186 		/* pick a rectangle */
187 		rsp = &rs[rn2(rscnt)];
188 		hx = rsp->rhx;
189 		hy = rsp->rhy;
190 		lx = rsp->rlx;
191 		ly = rsp->rly;
192 
193 		/* find size of room */
194 		if (secret)
195 			dx = dy = 1;
196 		else {
197 			dx = 2 + rn2((hx - lx - 8 > 20) ? 12 : 8);
198 			dy = 2 + rn2(4);
199 			if (dx * dy > 50)
200 				dy = 50 / dx;
201 		}
202 
203 		/* look whether our room will fit */
204 		if (hx - lx < dx + dx / 2 + 2 * xlim || hy - ly < dy + dy / 3 + 2 * ylim) {
205 			/* no, too small */
206 			/* maybe we throw this area out */
207 			if (secret || !rn2(MAXNROFROOMS + 1 - nroom - tryct)) {
208 				rscnt--;
209 				rs[rsmax] = *rsp;
210 				*rsp = rs[rscnt];
211 				rs[rscnt] = rs[rsmax];
212 				tryct = 0;
213 			} else
214 				tryct++;
215 			continue;
216 		}
217 
218 		lowx = lx + xlim + rn2(hx - lx - dx - 2 * xlim + 1);
219 		lowy = ly + ylim + rn2(hy - ly - dy - 2 * ylim + 1);
220 		hix = lowx + dx;
221 		hiy = lowy + dy;
222 
223 		if (maker(lowx, dx, lowy, dy)) {
224 			if (secret)
225 				return (1);
226 			addrs(lowx - 1, lowy - 1, hix + 1, hiy + 1);
227 			tryct = 0;
228 		} else if (tryct++ > 100)
229 			break;
230 	}
231 	return (0);		/* failed to make vault - very strange */
232 }
233 
234 static void
235 addrs(int lowx, int lowy, int hix, int hiy)
236 {
237 	struct rectangle *rsp;
238 	int lx, ly, hx, hy, xlim, ylim;
239 	boolean discarded;
240 
241 	xlim = XLIM + secret;
242 	ylim = YLIM + secret;
243 
244 	/* walk down since rscnt and rsmax change */
245 	for (rsp = &rs[rsmax - 1]; rsp >= rs; rsp--) {
246 		if ((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy ||
247 		    (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy)
248 			continue;
249 		if ((discarded = (rsp >= &rs[rscnt]))) {
250 			*rsp = rs[--rsmax];
251 		} else {
252 			rsmax--;
253 			rscnt--;
254 			*rsp = rs[rscnt];
255 			if (rscnt != rsmax)
256 				rs[rscnt] = rs[rsmax];
257 		}
258 		if (lowy - ly > 2 * ylim + 4)
259 			addrsx(lx, ly, hx, lowy - 2, discarded);
260 		if (lowx - lx > 2 * xlim + 4)
261 			addrsx(lx, ly, lowx - 2, hy, discarded);
262 		if (hy - hiy > 2 * ylim + 4)
263 			addrsx(lx, hiy + 2, hx, hy, discarded);
264 		if (hx - hix > 2 * xlim + 4)
265 			addrsx(hix + 2, ly, hx, hy, discarded);
266 	}
267 }
268 
269 /* discarded: piece of a discarded area */
270 static void
271 addrsx(int lx, int ly, int hx, int hy, bool discarded)
272 {
273 	struct rectangle *rsp;
274 
275 	/* check inclusions */
276 	for (rsp = rs; rsp < &rs[rsmax]; rsp++) {
277 		if (lx >= rsp->rlx && hx <= rsp->rhx &&
278 		    ly >= rsp->rly && hy <= rsp->rhy)
279 			return;
280 	}
281 
282 	/* make a new entry */
283 	if (rsmax >= MAXRS) {
284 #ifdef WIZARD
285 		if (wizard)
286 			pline("MAXRS may be too small.");
287 #endif /* WIZARD */
288 		return;
289 	}
290 	rsmax++;
291 	if (!discarded) {
292 		*rsp = rs[rscnt];
293 		rsp = &rs[rscnt];
294 		rscnt++;
295 	}
296 	rsp->rlx = lx;
297 	rsp->rly = ly;
298 	rsp->rhx = hx;
299 	rsp->rhy = hy;
300 }
301 
302 static int
303 comp(const void *vx, const void *vy)
304 {
305 	const struct mkroom *x, *y;
306 
307 	x = vx;
308 	y = vy;
309 	if (x->lx < y->lx)
310 		return (-1);
311 	return (x->lx > y->lx);
312 }
313 
314 static coord
315 finddpos(int xl, int yl, int xh, int yh)
316 {
317 	coord ff;
318 	int x, y;
319 
320 	x = (xl == xh) ? xl : (xl + rn2(xh - xl + 1));
321 	y = (yl == yh) ? yl : (yl + rn2(yh - yl + 1));
322 	if (okdoor(x, y))
323 		goto gotit;
324 
325 	for (x = xl; x <= xh; x++)
326 		for (y = yl; y <= yh; y++)
327 			if (okdoor(x, y))
328 				goto gotit;
329 
330 	for (x = xl; x <= xh; x++)
331 		for (y = yl; y <= yh; y++)
332 			if (levl[x][y].typ == DOOR || levl[x][y].typ == SDOOR)
333 				goto gotit;
334 	/* cannot find something reasonable -- strange */
335 	x = xl;
336 	y = yh;
337 gotit:
338 	ff.x = x;
339 	ff.y = y;
340 	return (ff);
341 }
342 
343 /* see whether it is allowable to create a door at [x,y] */
344 static bool
345 okdoor(int x, int y)
346 {
347 	if (levl[x - 1][y].typ == DOOR || levl[x + 1][y].typ == DOOR ||
348 	    levl[x][y + 1].typ == DOOR || levl[x][y - 1].typ == DOOR ||
349 	    levl[x - 1][y].typ == SDOOR || levl[x + 1][y].typ == SDOOR ||
350 	    levl[x][y - 1].typ == SDOOR || levl[x][y + 1].typ == SDOOR ||
351 	    (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
352 	    doorindex >= DOORMAX)
353 		return (0);
354 	return (1);
355 }
356 
357 static void
358 dodoor(int x, int y, struct mkroom *aroom)
359 {
360 	if (doorindex >= DOORMAX) {
361 		impossible("DOORMAX exceeded?");
362 		return;
363 	}
364 	if (!okdoor(x, y) && nxcor)
365 		return;
366 	dosdoor(x, y, aroom, rn2(8) ? DOOR : SDOOR);
367 }
368 
369 static void
370 dosdoor(int x, int y, struct mkroom *aroom, int type)
371 {
372 	struct mkroom *broom;
373 	int tmp;
374 
375 	if (!IS_WALL(levl[x][y].typ))	/* avoid SDOORs with '+' as scrsym */
376 		type = DOOR;
377 	levl[x][y].typ = type;
378 	if (type == DOOR)
379 		levl[x][y].scrsym = '+';
380 	aroom->doorct++;
381 	broom = aroom + 1;
382 	if (broom->hx < 0)
383 		tmp = doorindex;
384 	else
385 		for (tmp = doorindex; tmp > broom->fdoor; tmp--)
386 			doors[tmp] = doors[tmp - 1];
387 	doorindex++;
388 	doors[tmp].x = x;
389 	doors[tmp].y = y;
390 	for (; broom->hx >= 0; broom++)
391 		broom->fdoor++;
392 }
393 
394 /* Only called from makerooms() */
395 static bool
396 maker(schar lowx, schar ddx, schar lowy, schar ddy)
397 {
398 	struct mkroom *croom;
399 	int x, y, hix = lowx + ddx, hiy = lowy + ddy;
400 	int xlim = XLIM + secret, ylim = YLIM + secret;
401 
402 	if (nroom >= MAXNROFROOMS)
403 		return (0);
404 	if (lowx < XLIM)
405 		lowx = XLIM;
406 	if (lowy < YLIM)
407 		lowy = YLIM;
408 	if (hix > COLNO - XLIM - 1)
409 		hix = COLNO - XLIM - 1;
410 	if (hiy > ROWNO - YLIM - 1)
411 		hiy = ROWNO - YLIM - 1;
412 chk:
413 	if (hix <= lowx || hiy <= lowy)
414 		return (0);
415 
416 	/* check area around room (and make room smaller if necessary) */
417 	for (x = lowx - xlim; x <= hix + xlim; x++) {
418 		for (y = lowy - ylim; y <= hiy + ylim; y++) {
419 			if (levl[x][y].typ) {
420 #ifdef WIZARD
421 				if (wizard && !secret)
422 					pline("Strange area [%d,%d] in maker().", x, y);
423 #endif /* WIZARD */
424 				if (!rn2(3))
425 					return (0);
426 				if (x < lowx)
427 					lowx = x + xlim + 1;
428 				else
429 					hix = x - xlim - 1;
430 				if (y < lowy)
431 					lowy = y + ylim + 1;
432 				else
433 					hiy = y - ylim - 1;
434 				goto chk;
435 			}
436 		}
437 	}
438 
439 	croom = &rooms[nroom];
440 
441 	/* on low levels the room is lit (usually) */
442 	/* secret vaults are always lit */
443 	if ((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) {
444 		for (x = lowx - 1; x <= hix + 1; x++)
445 			for (y = lowy - 1; y <= hiy + 1; y++)
446 				levl[x][y].lit = 1;
447 		croom->rlit = 1;
448 	} else
449 		croom->rlit = 0;
450 	croom->lx = lowx;
451 	croom->hx = hix;
452 	croom->ly = lowy;
453 	croom->hy = hiy;
454 	croom->rtype = croom->doorct = croom->fdoor = 0;
455 
456 	for (x = lowx - 1; x <= hix + 1; x++)
457 		for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
458 			levl[x][y].scrsym = '-';
459 			levl[x][y].typ = HWALL;
460 		}
461 	for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
462 		for (y = lowy; y <= hiy; y++) {
463 			levl[x][y].scrsym = '|';
464 			levl[x][y].typ = VWALL;
465 		}
466 	for (x = lowx; x <= hix; x++)
467 		for (y = lowy; y <= hiy; y++) {
468 			levl[x][y].scrsym = '.';
469 			levl[x][y].typ = ROOM;
470 		}
471 
472 	smeq[nroom] = nroom;
473 	croom++;
474 	croom->hx = -1;
475 	nroom++;
476 	return (1);
477 }
478 
479 static void
480 makecorridors(void)
481 {
482 	int a, b;
483 
484 	nxcor = 0;
485 	for (a = 0; a < nroom - 1; a++)
486 		join(a, a + 1);
487 	for (a = 0; a < nroom - 2; a++)
488 		if (smeq[a] != smeq[a + 2])
489 			join(a, a + 2);
490 	for (a = 0; a < nroom; a++)
491 		for (b = 0; b < nroom; b++)
492 			if (smeq[a] != smeq[b])
493 				join(a, b);
494 	if (nroom > 2)
495 		for (nxcor = rn2(nroom) + 4; nxcor; nxcor--) {
496 			a = rn2(nroom);
497 			b = rn2(nroom - 2);
498 			if (b >= a)
499 				b += 2;
500 			join(a, b);
501 		}
502 }
503 
504 static void
505 join(int a, int b)
506 {
507 	coord cc, tt;
508 	int tx, ty, xx, yy;
509 	struct rm *crm;
510 	struct mkroom *croom, *troom;
511 	int dx, dy, dix, diy, cct;
512 
513 	croom = &rooms[a];
514 	troom = &rooms[b];
515 
516 	/*
517 	 * find positions cc and tt for doors in croom and troom and
518 	 * direction for a corridor between them
519 	 */
520 
521 	if (troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX)
522 		return;
523 	if (troom->lx > croom->hx) {
524 		dx = 1;
525 		dy = 0;
526 		xx = croom->hx + 1;
527 		tx = troom->lx - 1;
528 		cc = finddpos(xx, croom->ly, xx, croom->hy);
529 		tt = finddpos(tx, troom->ly, tx, troom->hy);
530 	} else if (troom->hy < croom->ly) {
531 		dy = -1;
532 		dx = 0;
533 		yy = croom->ly - 1;
534 		cc = finddpos(croom->lx, yy, croom->hx, yy);
535 		ty = troom->hy + 1;
536 		tt = finddpos(troom->lx, ty, troom->hx, ty);
537 	} else if (troom->hx < croom->lx) {
538 		dx = -1;
539 		dy = 0;
540 		xx = croom->lx - 1;
541 		tx = troom->hx + 1;
542 		cc = finddpos(xx, croom->ly, xx, croom->hy);
543 		tt = finddpos(tx, troom->ly, tx, troom->hy);
544 	} else {
545 		dy = 1;
546 		dx = 0;
547 		yy = croom->hy + 1;
548 		ty = troom->ly - 1;
549 		cc = finddpos(croom->lx, yy, croom->hx, yy);
550 		tt = finddpos(troom->lx, ty, troom->hx, ty);
551 	}
552 	xx = cc.x;
553 	yy = cc.y;
554 	tx = tt.x - dx;
555 	ty = tt.y - dy;
556 	if (nxcor && levl[xx + dx][yy + dy].typ)
557 		return;
558 	dodoor(xx, yy, croom);
559 
560 	cct = 0;
561 	while (xx != tx || yy != ty) {
562 		xx += dx;
563 		yy += dy;
564 
565 		/* loop: dig corridor at [xx,yy] and find new [xx,yy] */
566 		if (cct++ > 500 || (nxcor && !rn2(35)))
567 			return;
568 
569 		if (xx == COLNO - 1 || xx == 0 || yy == 0 || yy == ROWNO - 1)
570 			return;	/* impossible */
571 
572 		crm = &levl[xx][yy];
573 		if (!(crm->typ)) {
574 			if (rn2(100)) {
575 				crm->typ = CORR;
576 				crm->scrsym = CORR_SYM;
577 				if (nxcor && !rn2(50))
578 					mkobj_at(ROCK_SYM, xx, yy);
579 			} else {
580 				crm->typ = SCORR;
581 				crm->scrsym = ' ';
582 			}
583 		} else if (crm->typ != CORR && crm->typ != SCORR) {
584 			/* strange ... */
585 			return;
586 		}
587 		/* find next corridor position */
588 		dix = abs(xx - tx);
589 		diy = abs(yy - ty);
590 
591 		/* do we have to change direction ? */
592 		if (dy && dix > diy) {
593 			int ddx = (xx > tx) ? -1 : 1;
594 
595 			crm = &levl[xx + ddx][yy];
596 			if (!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
597 				dx = ddx;
598 				dy = 0;
599 				continue;
600 			}
601 		} else if (dx && diy > dix) {
602 			int ddy = (yy > ty) ? -1 : 1;
603 
604 			crm = &levl[xx][yy + ddy];
605 			if (!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
606 				dy = ddy;
607 				dx = 0;
608 				continue;
609 			}
610 		}
611 
612 		/* continue straight on? */
613 		crm = &levl[xx + dx][yy + dy];
614 		if (!crm->typ || crm->typ == CORR || crm->typ == SCORR)
615 			continue;
616 
617 		/* no, what must we do now?? */
618 		if (dx) {
619 			dx = 0;
620 			dy = (ty < yy) ? -1 : 1;
621 			crm = &levl[xx + dx][yy + dy];
622 			if (!crm->typ || crm->typ == CORR || crm->typ == SCORR)
623 				continue;
624 			dy = -dy;
625 			continue;
626 		} else {
627 			dy = 0;
628 			dx = (tx < xx) ? -1 : 1;
629 			crm = &levl[xx + dx][yy + dy];
630 			if (!crm->typ || crm->typ == CORR || crm->typ == SCORR)
631 				continue;
632 			dx = -dx;
633 			continue;
634 		}
635 	}
636 
637 	/* we succeeded in digging the corridor */
638 	dodoor(tt.x, tt.y, troom);
639 
640 	if (smeq[a] < smeq[b])
641 		smeq[b] = smeq[a];
642 	else
643 		smeq[a] = smeq[b];
644 }
645 
646 static void
647 make_niches(void)
648 {
649 	int ct = rnd(nroom / 2 + 1);
650 	while (ct--)
651 		makeniche(FALSE);
652 }
653 
654 static void
655 makevtele(void)
656 {
657 	makeniche(TRUE);
658 }
659 
660 static void
661 makeniche(bool with_trap)
662 {
663 	struct mkroom *aroom;
664 	struct rm *rm;
665 	int vct = 8;
666 	coord dd;
667 	int dy, xx, yy;
668 	struct trap *ttmp;
669 
670 	if (doorindex < DOORMAX)
671 		while (vct--) {
672 			aroom = &rooms[rn2(nroom - 1)];
673 			if (aroom->rtype != 0)	/* not an ordinary room */
674 				continue;
675 			if (aroom->doorct == 1 && rn2(5))
676 				continue;
677 			if (rn2(2)) {
678 				dy = 1;
679 				dd = finddpos(aroom->lx, aroom->hy + 1,
680 				    aroom->hx,
681 				    aroom->hy + 1);
682 			} else {
683 				dy = -1;
684 				dd = finddpos(aroom->lx, aroom->ly - 1,
685 				    aroom->hx,
686 				    aroom->ly - 1);
687 			}
688 			xx = dd.x;
689 			yy = dd.y;
690 			if ((rm = &levl[xx][yy + dy])->typ)
691 				continue;
692 			if (with_trap || !rn2(4)) {
693 				rm->typ = SCORR;
694 				rm->scrsym = ' ';
695 				if (with_trap) {
696 					ttmp = maketrap(xx, yy + dy, TELEP_TRAP);
697 					ttmp->once = 1;
698 					make_engr_at(xx, yy - dy, "ad ae?ar um");
699 				}
700 				dosdoor(xx, yy, aroom, SDOOR);
701 			} else {
702 				rm->typ = CORR;
703 				rm->scrsym = CORR_SYM;
704 				if (rn2(7))
705 					dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
706 				else {
707 					mksobj_at(SCR_TELEPORTATION, xx, yy + dy);
708 					if (!rn2(3))
709 						mkobj_at(0, xx, yy + dy);
710 				}
711 			}
712 			return;
713 		}
714 }
715 
716 /* make a trap somewhere (in croom if mazeflag = 0) */
717 void
718 mktrap(int num, int mazeflag, struct mkroom *croom)
719 {
720 	struct trap *ttmp;
721 	int kind, nopierc, nomimic, fakedoor, fakegold, tryct = 0;
722 	xchar mx, my;
723 
724 	if (!num || num >= TRAPNUM) {
725 		nopierc = (dlevel < 4) ? 1 : 0;
726 		nomimic = (dlevel < 9 || goldseen) ? 1 : 0;
727 		if (strchr(fut_geno, 'M'))
728 			nomimic = 1;
729 		kind = rn2(TRAPNUM - nopierc - nomimic);
730 		/* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
731 	} else
732 		kind = num;
733 
734 	if (kind == MIMIC) {
735 		struct monst *mtmp;
736 
737 		fakedoor = (!rn2(3) && !mazeflag);
738 		fakegold = (!fakedoor && !rn2(2));
739 		if (fakegold)
740 			goldseen = TRUE;
741 		do {
742 			if (++tryct > 200)
743 				return;
744 			if (fakedoor) {
745 				/* note: fakedoor maybe on actual door */
746 				if (rn2(2)) {
747 					if (rn2(2))
748 						mx = croom->hx + 1;
749 					else
750 						mx = croom->lx - 1;
751 					my = somey();
752 				} else {
753 					if (rn2(2))
754 						my = croom->hy + 1;
755 					else
756 						my = croom->ly - 1;
757 					mx = somex();
758 				}
759 			} else if (mazeflag) {
760 				coord mm;
761 				mm = mazexy();
762 				mx = mm.x;
763 				my = mm.y;
764 			} else {
765 				mx = somex();
766 				my = somey();
767 			}
768 		} while (m_at(mx, my) || levl[mx][my].typ == STAIRS);
769 		if ((mtmp = makemon(PM_MIMIC, mx, my)) != NULL) {
770 			mtmp->mimic = 1;
771 			mtmp->mappearance =
772 				fakegold ? '$' : fakedoor ? '+' :
773 				(mazeflag && rn2(2)) ? AMULET_SYM :
774 				"=/)%?![<>"[rn2(9)];
775 		}
776 		return;
777 	}
778 
779 	do {
780 		if (++tryct > 200)
781 			return;
782 		if (mazeflag) {
783 			coord mm;
784 			mm = mazexy();
785 			mx = mm.x;
786 			my = mm.y;
787 		} else {
788 			mx = somex();
789 			my = somey();
790 		}
791 	} while (t_at(mx, my) || levl[mx][my].typ == STAIRS);
792 	ttmp = maketrap(mx, my, kind);
793 	if (mazeflag && !rn2(10) && ttmp->ttyp < PIERC)
794 		ttmp->tseen = 1;
795 }
796