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