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