Merge branch 'vendor/OPENSSL'
[games.git] / games / hack / hack.mklev.c
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 }