hack.mklev.c 20 KB

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