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