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