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