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 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 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 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 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 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 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 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 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 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 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 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 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 677 make_niches(void) 678 { 679 int ct = rnd(nroom/2 + 1); 680 while(ct--) makeniche(FALSE); 681 } 682 683 static void 684 makevtele(void) 685 { 686 makeniche(TRUE); 687 } 688 689 static void 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 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