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