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