Difference between revisions of "Source:NetHack 3.1.0/sp lev.c"
Jump to navigation
Jump to search
m (Automated source code upload) |
Kernigh bot (talk | contribs) m (NetHack 3.1.0/sp lev.c moved to Source:NetHack 3.1.0/sp lev.c: Robot: moved page) |
(No difference)
|
Latest revision as of 07:32, 4 March 2008
Below is the full text to sp_lev.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/sp_lev.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)sp_lev.c 3.1 92/11/14 */ 2. /* Copyright (c) 1989 by Jean-Christophe Collet */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. /* 6. * This file contains the various functions that are related to the special 7. * levels. 8. * It contains also the special level loader. 9. * 10. */ 11. 12. #include "hack.h" 13. /*#define DEBUG /* uncomment to enable code debugging */ 14. 15. #ifdef DEBUG 16. # ifdef WIZARD 17. #define debugpline if (wizard) pline 18. # else 19. #define debugpline pline 20. # endif 21. #endif 22. 23. #include "sp_lev.h" 24. #include "rect.h" 25. 26. extern void FDECL(mkmap, (lev_init *)); 27. 28. static void FDECL(get_room_loc, (schar *, schar *, struct mkroom *)); 29. static void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *)); 30. static void FDECL(create_trap, (trap *, struct mkroom *)); 31. static void FDECL(create_monster, (monster *, struct mkroom *)); 32. static void FDECL(create_object, (object *, struct mkroom *)); 33. static void FDECL(create_stairs, (stair *, struct mkroom *)); 34. static void FDECL(create_altar, (altar *, struct mkroom *)); 35. static void FDECL(create_gold, (gold *, struct mkroom *)); 36. static void FDECL(create_feature, (int,int,struct mkroom *,int)); 37. static boolean FDECL(search_door, (struct mkroom *, xchar *, xchar *, 38. XCHAR_P, int)); 39. static void NDECL(fix_stair_rooms); 40. static void FDECL(create_corridor, (corridor *)); 41. 42. static boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P, 43. XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); 44. 45. #if defined(MICRO) && !defined(AMIGA) 46. # define RDMODE "rb" 47. #else 48. # define RDMODE "r" 49. #endif 50. 51. #define LEFT 1 52. #define H_LEFT 2 53. #define CENTER 3 54. #define H_RIGHT 4 55. #define RIGHT 5 56. 57. #define TOP 1 58. #define BOTTOM 5 59. 60. #define sq(x) ((x)*(x)) 61. 62. #define XLIM 4 63. #define YLIM 3 64. 65. #define Fread (void)fread 66. #define New(type) (type *) alloc(sizeof(type)) 67. #define NewTab(type, size) (type **) alloc(sizeof(type *) * size) 68. #define Free(ptr) if(ptr) free((genericptr_t) (ptr)) 69. 70. static walk NEARDATA walklist[50]; 71. extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */ 72. 73. static char Map[COLNO][ROWNO]; 74. static char robjects[10], rloc_x[10], rloc_y[10], rmonst[10]; 75. static aligntyp ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL }; 76. static xchar NEARDATA xstart, NEARDATA ystart; 77. static char NEARDATA xsize, NEARDATA ysize; 78. 79. static void FDECL(make_walls_nondiggable, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P)); 80. static int NDECL(rnddoor); 81. static int NDECL(rndtrap); 82. static void FDECL(get_location, (schar *,schar *,int)); 83. static void FDECL(sp_lev_shuffle, (char *,char *,int)); 84. static void FDECL(light_region, (region *)); 85. static void FDECL(load_common_data, (FILE *,int)); 86. static boolean FDECL(load_rooms, (FILE *)); 87. static void FDECL(maze1xy, (coord *)); 88. static boolean FDECL(load_maze, (FILE *)); 89. static void FDECL(create_door, (room_door *, struct mkroom *)); 90. static void FDECL(free_rooms,(room **, int)); 91. static void FDECL(build_room, (room *, room*)); 92. 93. char *lev_message = 0; 94. lev_region *lregions = 0; 95. int num_lregions = 0; 96. lev_init init_lev; 97. 98. /* 99. * Make walls of the area (x1, y1, x2, y2) non diggable 100. */ 101. 102. static void 103. make_walls_nondiggable(x1,y1,x2,y2) 104. xchar x1, y1, x2, y2; 105. { 106. register xchar x, y; 107. 108. for(y = y1; y <= y2; y++) 109. for(x = x1; x <= x2; x++) 110. if(IS_STWALL(levl[x][y].typ)) 111. levl[x][y].diggable |= W_NONDIGGABLE; 112. } 113. 114. /* 115. * Choose randomly the state (nodoor, open, closed or locked) for a door 116. */ 117. 118. static int 119. rnddoor() 120. { 121. int i; 122. 123. i = 1 << rn2(5); 124. i >>= 1; 125. return i; 126. } 127. 128. /* 129. * Select a random trap 130. */ 131. 132. static int 133. rndtrap() 134. { 135. int rtrap, no_tdoor = !Can_dig_down(&u.uz); 136. do { 137. rtrap = rnd(TRAPNUM-1); 138. } while (rtrap == MAGIC_PORTAL || (no_tdoor && rtrap == TRAPDOOR)); 139. return(rtrap); 140. } 141. 142. /* 143. * Coordinates in special level files are handled specially: 144. * 145. * if x or y is -11, we generate a random coordinate. 146. * if x or y is between -1 and -10, we read one from the corresponding 147. * register (x0, x1, ... x9). 148. * if x or y is nonnegative, we convert it from relative to the local map 149. * to global coordinates. 150. * The "humidity" flag is used to insure that engravings aren't 151. * created underwater, or eels on dry land. 152. */ 153. #define DRY 0x1 154. #define WET 0x2 155. 156. static boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int)); 157. 158. static void 159. get_location(x, y, humidity) 160. schar *x, *y; 161. int humidity; 162. { 163. int cpt = 0; 164. 165. if (*x >= 0) { /* normal locations */ 166. *x += xstart; 167. *y += ystart; 168. } else if (*x > -11) { /* special locations */ 169. *y = ystart + rloc_y[ - *y - 1]; 170. *x = xstart + rloc_x[ - *x - 1]; 171. } else { /* random location */ 172. do { 173. *x = xstart + rn2((int)xsize); 174. *y = ystart + rn2((int)ysize); 175. if (is_ok_location(*x,*y,humidity)) break; 176. } while (++cpt < 100); 177. if (cpt >= 100) { 178. register int xx, yy; 179. /* last try */ 180. for (xx = 0; xx < xsize; xx++) 181. for (yy = 0; yy < ysize; yy++) { 182. *x = xstart + xx; 183. *y = ystart + yy; 184. if (is_ok_location(*x,*y,humidity)) goto found_it; 185. } 186. panic("get_location: can't find a place!"); 187. } 188. } 189. found_it:; 190. 191. if (*x <= 0 || *x >= COLNO || *y < 0 || *y >= ROWNO) { 192. impossible("get_location: (%d,%d) out of bounds", *x, *y); 193. *x = x_maze_max; *y = y_maze_max; 194. } 195. } 196. 197. static boolean 198. is_ok_location(x, y, humidity) 199. register schar x, y; 200. register int humidity; 201. { 202. register int typ; 203. register boolean okplace = FALSE; 204. 205. if (humidity & DRY) { 206. typ = levl[x][y].typ; 207. okplace = (typ == ROOM || typ == AIR || 208. typ == CLOUD || typ == CORR); 209. } 210. if (humidity & WET) { 211. if (is_pool(x,y) || is_lava(x,y)) 212. okplace = TRUE; 213. } 214. return okplace; 215. } 216. 217. /* 218. * Shuffle the registers for locations, objects or monsters 219. */ 220. 221. static void 222. sp_lev_shuffle(list1, list2, n) 223. char list1[], list2[]; 224. int n; 225. { 226. register int i, j; 227. register char k; 228. 229. for (i = n - 1; i > 0; i--) { 230. if ((j = rn2(i + 1)) == i) continue; 231. k = list1[j]; 232. list1[j] = list1[i]; 233. list1[i] = k; 234. if (list2) { 235. k = list2[j]; 236. list2[j] = list2[i]; 237. list2[i] = k; 238. } 239. } 240. } 241. 242. /* 243. * Get a relative position inside a room. 244. * negative values for x or y means RANDOM! 245. */ 246. 247. static void 248. get_room_loc(x,y, croom) 249. schar *x, *y; 250. struct mkroom *croom; 251. { 252. coord c; 253. 254. if (*x <0 && *y <0) { 255. if (somexy(croom, &c)) { 256. *x = c.x; 257. *y = c.y; 258. } else 259. panic("get_room_loc : can't find a place!"); 260. } else { 261. if (*x < 0) 262. *x = rn2(croom->hx - croom->lx + 1); 263. if (*y < 0) 264. *y = rn2(croom->hy - croom->ly + 1); 265. *x += croom->lx; 266. *y += croom->ly; 267. } 268. } 269. 270. /* 271. * Get a relative position inside a room. 272. * negative values for x or y means RANDOM! 273. */ 274. 275. static void 276. get_free_room_loc(x,y, croom) 277. schar *x, *y; 278. struct mkroom *croom; 279. { 280. schar try_x, try_y; 281. register int trycnt = 0; 282. 283. do { 284. try_x = *x, try_y = *y; 285. get_room_loc(&try_x, &try_y, croom); 286. } while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100); 287. 288. if (trycnt > 100) 289. panic("get_free_room_loc: can't find a place!"); 290. *x = try_x, *y = try_y; 291. } 292. 293. boolean 294. check_room(lowx, ddx, lowy, ddy, vault) 295. xchar *lowx, *ddx, *lowy, *ddy; 296. boolean vault; 297. { 298. register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy; 299. register struct rm *lev; 300. int xlim, ylim, ymax; 301. 302. xlim = XLIM + (vault ? 1 : 0); 303. ylim = YLIM + (vault ? 1 : 0); 304. 305. if (*lowx < 3) *lowx = 3; 306. if (*lowy < 2) *lowy = 2; 307. if (hix > COLNO-3) hix = COLNO-3; 308. if (hiy > ROWNO-3) hiy = ROWNO-3; 309. chk: 310. if (hix <= *lowx || hiy <= *lowy) return FALSE; 311. 312. /* check area around room (and make room smaller if necessary) */ 313. for (x = *lowx - xlim; x<= hix + xlim; x++) { 314. if(x <= 0 || x >= COLNO) continue; 315. y = *lowy - ylim; ymax = hiy + ylim; 316. if(y < 0) y = 0; 317. if(ymax >= ROWNO) ymax = (ROWNO-1); 318. lev = &levl[x][y]; 319. for (; y <= ymax; y++) { 320. if (lev++->typ) { 321. #ifdef DEBUG 322. if(!vault) 323. debugpline("strange area [%d,%d] in check_room.",x,y); 324. #endif 325. if (!rn2(3)) return FALSE; 326. if (x < *lowx) 327. *lowx = x + xlim + 1; 328. else 329. hix = x - xlim - 1; 330. if (y < *lowy) 331. *lowy = y + ylim + 1; 332. else 333. hiy = y - ylim - 1; 334. goto chk; 335. } 336. } 337. } 338. *ddx = hix - *lowx; 339. *ddy = hiy - *lowy; 340. return TRUE; 341. } 342. 343. /* 344. * Create a new room. 345. * This is still very incomplete... 346. */ 347. 348. boolean 349. create_room(x,y,w,h,xal,yal,rtype,rlit) 350. xchar x,y; 351. xchar w,h; 352. xchar xal,yal; 353. xchar rtype, rlit; 354. { 355. xchar xabs, yabs; 356. int wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp; 357. NhRect *r1 = 0, r2; 358. int trycnt = 0; 359. boolean vault = FALSE; 360. int xlim = XLIM, ylim = YLIM; 361. 362. if (rtype == -1) /* Is the type random ? */ 363. rtype = OROOM; 364. 365. if (rtype == VAULT) { 366. vault = TRUE; 367. xlim++; 368. ylim++; 369. } 370. 371. /* on low levels the room is lit (usually) */ 372. /* some other rooms may require lighting */ 373. 374. /* is light state random ? */ 375. if (rlit == -1) 376. rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE; 377. 378. /* 379. * Here we will try to create a room. If some parameters are 380. * random we are willing to make several try before we give 381. * it up. 382. */ 383. do { 384. xchar xborder, yborder; 385. wtmp = w; htmp = h; 386. xtmp = x; ytmp = y; 387. xaltmp = xal; yaltmp = yal; 388. 389. /* First case : a totaly random room */ 390. 391. if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 && 392. yaltmp < 0) || vault) { 393. xchar hx, hy, lx, ly, dx, dy; 394. r1 = rnd_rect(); /* Get a random rectangle */ 395. 396. if (!r1) { /* No more free rectangles ! */ 397. #ifdef DEBUG 398. debugpline("No more rects..."); 399. #endif 400. return FALSE; 401. } 402. hx = r1->hx; 403. hy = r1->hy; 404. lx = r1->lx; 405. ly = r1->ly; 406. if (vault) 407. dx = dy = 1; 408. else { 409. dx = 2 + rn2((hx-lx > 28) ? 12 : 8); 410. dy = 2 + rn2(4); 411. if(dx*dy > 50) 412. dy = 50/dx; 413. } 414. xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1; 415. yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1; 416. if(hx-lx < dx + 3 + xborder || 417. hy-ly < dy + 3 + yborder) { 418. r1 = 0; 419. continue; 420. } 421. xabs = lx + (lx > 0 ? xlim : 3) 422. + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1); 423. yabs = ly + (ly > 0 ? ylim : 2) 424. + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1); 425. if (ly == 0 && hy >= (ROWNO-1) && 426. (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) { 427. yabs = rn1(3, 2); 428. if(nroom < 4 && dy>1) dy--; 429. } 430. if (!check_room(&xabs, &dx, &yabs, &dy, vault)) { 431. r1 = 0; 432. continue; 433. } 434. wtmp = dx+1; 435. htmp = dy+1; 436. r2.lx = xabs-1; r2.ly = yabs-1; 437. r2.hx = xabs + wtmp; 438. r2.hy = yabs + htmp; 439. } else { /* Only some parameters are random */ 440. int rndpos = 0; 441. if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */ 442. xtmp = rnd(5); 443. ytmp = rnd(5); 444. rndpos = 1; 445. } 446. if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */ 447. wtmp = rn1(15, 3); 448. htmp = rn1(8, 2); 449. } 450. if (xaltmp == -1) /* Horizontal alignment is RANDOM */ 451. xaltmp = rnd(3); 452. if (yaltmp == -1) /* Vertical alignment is RANDOM */ 453. yaltmp = rnd(3); 454. 455. /* Try to generate real (absolute) coordinates here! */ 456. 457. xabs = (((xtmp-1) * COLNO) / 5) + 1; 458. yabs = (((ytmp-1) * ROWNO) / 5) + 1; 459. switch (xaltmp) { 460. case LEFT: 461. break; 462. case RIGHT: 463. xabs += (COLNO / 5) - wtmp; 464. break; 465. case CENTER: 466. xabs += ((COLNO / 5) - wtmp) / 2; 467. break; 468. } 469. switch (yaltmp) { 470. case TOP: 471. break; 472. case BOTTOM: 473. yabs += (ROWNO / 5) - htmp; 474. break; 475. case CENTER: 476. yabs += ((ROWNO / 5) - htmp) / 2; 477. break; 478. } 479. 480. if (xabs + wtmp - 1 > COLNO - 2) 481. xabs = COLNO - wtmp - 3; 482. 483. if (xabs < 2) 484. xabs = 2; 485. 486. if (yabs + htmp - 1> ROWNO - 2) 487. yabs = ROWNO - htmp - 3; 488. 489. if (yabs < 2) 490. yabs = 2; 491. /* Try to find a rectangle that fit our room ! */ 492. 493. r2.lx = xabs-1; r2.ly = yabs-1; 494. r2.hx = xabs + wtmp + rndpos; 495. r2.hy = yabs + htmp + rndpos; 496. r1 = get_rect(&r2); 497. } 498. } while (++trycnt <= 100 && !r1); 499. if (!r1) { /* creation of room failed ? */ 500. return FALSE; 501. } 502. split_rects(r1, &r2); 503. 504. if (!vault) { 505. smeq[nroom] = nroom; 506. add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1, 507. rlit, rtype, FALSE); 508. } else { 509. rooms[nroom].lx = xabs; 510. rooms[nroom].ly = yabs; 511. } 512. return TRUE; 513. } 514. 515. /* 516. * Create a subroom in room proom at pos x,y with width w & height h. 517. * x & y are relative to the parent room. 518. */ 519. 520. static boolean 521. create_subroom(proom, x, y, w, h, rtype, rlit) 522. struct mkroom *proom; 523. xchar x,y; 524. xchar w,h; 525. xchar rtype, rlit; 526. { 527. xchar width, height; 528. 529. width = proom->hx - proom->lx + 1; 530. height = proom->hy - proom->ly + 1; 531. 532. /* There is a minimum size for the parent room */ 533. if (width < 4 || height < 4) 534. return FALSE; 535. 536. /* Check for random position, size, etc... */ 537. 538. if (w == -1) 539. w = rnd(width - 3); 540. if (h == -1) 541. h = rnd(height - 3); 542. if (x == -1) 543. x = rnd(width - w - 1) - 1; 544. if (y == -1) 545. y = rnd(height - h - 1) - 1; 546. if (x == 1) 547. x = 0; 548. if (y == 1) 549. y = 0; 550. if ((x + w + 1) == width) 551. x++; 552. if ((y + h + 1) == height) 553. y++; 554. if (rtype == -1) 555. rtype = OROOM; 556. if (rlit == -1) 557. rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE; 558. add_subroom(proom, proom->lx + x, proom->ly + y, 559. proom->lx + x + w - 1, proom->ly + y + h - 1, 560. rlit, rtype, FALSE); 561. return TRUE; 562. } 563. 564. /* 565. * Create a new door in a room. 566. * It's placed on a wall (north, south, east or west). 567. */ 568. 569. static void 570. create_door(dd, broom) 571. room_door *dd; 572. struct mkroom *broom; 573. { 574. int x, y; 575. int trycnt = 0; 576. 577. if (dd->secret == -1) 578. dd->secret = rn2(2); 579. 580. if (dd->mask == -1) { 581. /* is it a locked door, closed, or a doorway? */ 582. if (!dd->secret) { 583. if(!rn2(3)) { 584. if(!rn2(5)) 585. dd->mask = D_ISOPEN; 586. else if(!rn2(6)) 587. dd->mask = D_LOCKED; 588. else 589. dd->mask = D_CLOSED; 590. if (dd->mask != D_ISOPEN && !rn2(25)) 591. dd->mask |= D_TRAPPED; 592. } else 593. dd->mask = D_NODOOR; 594. } else { 595. if(!rn2(5)) dd->mask = D_LOCKED; 596. else dd->mask = D_CLOSED; 597. 598. if(!rn2(20)) dd->mask |= D_TRAPPED; 599. } 600. } 601. 602. do { 603. register int dwall, dpos; 604. 605. dwall = dd->wall; 606. if (dwall == -1) /* The wall is RANDOM */ 607. dwall = 1 << rn2(4); 608. 609. dpos = dd->pos; 610. if (dpos == -1) /* The position is RANDOM */ 611. dpos = rn2((dwall == W_WEST || dwall == W_EAST) ? 612. (broom->hy - broom->ly) : (broom->hx - broom->lx)); 613. 614. /* Convert wall and pos into an absolute coordinate! */ 615. 616. switch (dwall) { 617. case W_NORTH: 618. y = broom->ly - 1; 619. x = broom->lx + dpos; 620. break; 621. case W_SOUTH: 622. y = broom->hy + 1; 623. x = broom->lx + dpos; 624. break; 625. case W_WEST: 626. x = broom->lx - 1; 627. y = broom->ly + dpos; 628. break; 629. case W_EAST: 630. x = broom->hx + 1; 631. y = broom->ly + dpos; 632. break; 633. default: 634. x = y = 0; 635. panic("create_door: No wall for door!"); 636. break; 637. } 638. if (okdoor(x,y)) 639. break; 640. } while (++trycnt <= 100); 641. if (trycnt > 100) { 642. impossible("create_door: Can't find a proper place!"); 643. return; 644. } 645. add_door(x,y,broom); 646. levl[x][y].typ = (dd->secret ? SDOOR : DOOR); 647. levl[x][y].doormask = dd->mask; 648. } 649. 650. /* 651. * Create a secret door in croom on any one of the specified walls. 652. */ 653. void 654. create_secret_door(croom, walls) 655. struct mkroom *croom; 656. xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */ 657. { 658. xchar sx, sy; /* location of the secret door */ 659. int count; 660. 661. for(count = 0; count < 100; count++) { 662. sx = rn1(croom->hx - croom->lx + 1, croom->lx); 663. sy = rn1(croom->hy - croom->ly + 1, croom->ly); 664. 665. switch(rn2(4)) { 666. case 0: /* top */ 667. if(!(walls & W_NORTH)) continue; 668. sy = croom->ly-1; break; 669. case 1: /* bottom */ 670. if(!(walls & W_SOUTH)) continue; 671. sy = croom->hy+1; break; 672. case 2: /* left */ 673. if(!(walls & W_EAST)) continue; 674. sx = croom->lx-1; break; 675. case 3: /* right */ 676. if(!(walls & W_WEST)) continue; 677. sx = croom->hx+1; break; 678. } 679. 680. if(okdoor(sx,sy)) { 681. levl[sx][sy].typ = SDOOR; 682. levl[sx][sy].doormask = D_CLOSED; 683. add_door(sx,sy,croom); 684. return; 685. } 686. } 687. 688. impossible("couldn't create secret door on any walls 0x%x", walls); 689. } 690. 691. /* 692. * Create a trap in a room. 693. */ 694. 695. static void 696. create_trap(t,croom) 697. trap *t; 698. struct mkroom *croom; 699. { 700. schar x,y; 701. coord tm; 702. 703. x = t->x; 704. y = t->y; 705. if (croom) 706. get_free_room_loc(&x, &y, croom); 707. else 708. get_location(&x, &y, DRY); 709. 710. tm.x = x; 711. tm.y = y; 712. 713. mktrap(t->type, 1, (struct mkroom*) 0, &tm); 714. } 715. 716. /* 717. * Create a monster in a room. 718. */ 719. 720. static void 721. create_monster(m,croom) 722. monster *m; 723. struct mkroom *croom; 724. { 725. struct monst *mtmp; 726. schar x,y; 727. char class; 728. aligntyp amask; 729. struct permonst *pm; 730. 731. if (m->class >= 0) { 732. class = (char) def_char_to_monclass((char)m->class); 733. if (class == MAXMCLASSES) goto bad_class; 734. } else if (m->class > -11) { 735. class = (char) def_char_to_monclass(rmonst[- m->class - 1]); 736. if (class == MAXMCLASSES) { 737. bad_class: 738. panic("create_monster: unknown monster class '%c'", m->class); 739. } 740. } else 741. class = 0; 742. 743. amask = (m->align <= -11) ? induced_align(80) : 744. (m->align < 0 ? ralign[-m->align-1] : m->align); 745. 746. if (!class) 747. pm = (struct permonst *) 0; 748. else if (m->id != -1) { 749. #ifdef MULDGN 750. if(pl_character[0] == 'E' && m->id == PM_EARENDIL) 751. m->id += flags.female; 752. #endif 753. pm = &mons[m->id]; 754. } else { 755. pm = mkclass(class,G_NOGEN); 756. /* if we can't get class for a specific monster type, 757. it means, that it's extinct, genocided, or unique, 758. and shouldn't be created. */ 759. if (!pm) return; 760. } 761. 762. x = m->x; 763. y = m->y; 764. if (croom) 765. get_room_loc(&x, &y, croom); 766. else { 767. if (!pm || !is_swimmer(pm)) 768. get_location(&x, &y, DRY); 769. else if (pm->mlet == S_EEL) 770. get_location(&x, &y, WET); 771. else 772. get_location(&x, &y, DRY|WET); 773. } 774. 775. 776. if(m->align != -12) 777. mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful); 778. else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD) 779. mtmp = mk_mplayer(pm, x, y, FALSE); 780. else mtmp = makemon(pm, x, y); 781. 782. if (mtmp) { 783. /* handle specific attributes for some special monsters */ 784. if (m->name) mtmp = christen_monst(mtmp, m->name); 785. 786. /* 787. * This is currently hardwired for mimics only. It should 788. * eventually be expanded. 789. */ 790. if (m->appear_as && mtmp->data->mlet == S_MIMIC) { 791. int i; 792. 793. switch (m->appear) { 794. case M_AP_NOTHING: 795. impossible( 796. "create_monster: mon has an appearance, \"%s\", but no type", 797. m->appear_as); 798. break; 799. 800. case M_AP_FURNITURE: 801. for (i = 0; i < MAXPCHARS; i++) 802. if (!strcmp(defsyms[i].explanation, m->appear_as)) 803. break; 804. if (i == MAXPCHARS) { 805. impossible( 806. "create_monster: can't find feature \"%s\"", 807. m->appear_as); 808. } else { 809. mtmp->m_ap_type = M_AP_FURNITURE; 810. mtmp->mappearance = i; 811. } 812. break; 813. 814. case M_AP_OBJECT: 815. for (i = 0; i < NROFOBJECTS; i++) 816. if (!strcmp(OBJ_NAME(objects[i]), m->appear_as)) 817. break; 818. if (i == NROFOBJECTS) { 819. impossible( 820. "create_monster: can't find object \"%s\"", 821. m->appear_as); 822. } else { 823. mtmp->m_ap_type = M_AP_OBJECT; 824. mtmp->mappearance = i; 825. } 826. break; 827. 828. case M_AP_MONSTER: 829. /* note: mimics don't appear as monsters! */ 830. /* (but chameleons can :-) */ 831. default: 832. impossible( 833. "create_monster: unimplemented mon appear type [%d,\"%s\"]", 834. m->appear, m->appear_as); 835. break; 836. } 837. if (does_block(x, y, &levl[x][y])) 838. block_point(x, y); 839. } 840. 841. if (m->peaceful >= 0) { 842. mtmp->mpeaceful = m->peaceful; 843. /* changed mpeaceful again; have to reset malign */ 844. set_malign(mtmp); 845. } 846. if (m->asleep >= 0) mtmp->msleep = m->asleep; 847. } 848. } 849. 850. /* 851. * Create an object in a room. 852. */ 853. 854. static void 855. create_object(o,croom) 856. object *o; 857. struct mkroom *croom; 858. { 859. struct obj *otmp; 860. schar x,y; 861. char c; 862. 863. x = o->x; y = o->y; 864. if (croom) 865. get_room_loc(&x, &y, croom); 866. else 867. get_location(&x, &y, DRY); 868. 869. if (o->class >= 0) 870. c = o->class; 871. else if (o->class > -11) 872. c = robjects[ -(o->class+1)]; 873. else 874. c = 0; 875. 876. if (!c) 877. otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE); 878. else if (o->id != -1) 879. otmp = mksobj_at(o->id, x, y, TRUE); 880. else { 881. /* 882. * The special levels are compiled with the default "text" object 883. * class characters. We must convert them to the internal format. 884. */ 885. char oclass = (char) def_char_to_objclass(c); 886. 887. if (oclass == MAXOCLASSES) 888. panic("create_object: unexpected object class '%c'",c); 889. otmp = mkobj_at(oclass, x, y, TRUE); 890. } 891. 892. if (o->spe != -127) /* That means NOT RANDOM! */ 893. otmp->spe = o->spe; 894. 895. switch (o->curse_state) { 896. case 1: bless(otmp); break; /* BLESSED */ 897. case 2: unbless(otmp); uncurse(otmp); break; /* uncursed */ 898. case 3: curse(otmp); break; /* CURSED */ 899. default: break; /* Otherwise it's random and we're happy 900. * with what mkobj gave us! */ 901. } 902. 903. /* corpsenm is "empty" if -1, random if -2, otherwise specific */ 904. if (o->corpsenm == -2) otmp->corpsenm = rndmonnum(); 905. else if (o->corpsenm != -1) otmp->corpsenm = o->corpsenm; 906. 907. if (o->name) { /* Give a name to that object */ 908. /* Note: oname() is safe since otmp is first in chains */ 909. otmp = oname(otmp, o->name, 0); 910. fobj = otmp; 911. level.objects[x][y] = otmp; 912. } 913. stackobj(otmp); 914. } 915. 916. /* 917. * Create stairs in a room. 918. * 919. */ 920. 921. static void 922. create_stairs(s,croom) 923. stair *s; 924. struct mkroom *croom; 925. { 926. schar x,y; 927. 928. x = s->x; y = s->y; 929. get_free_room_loc(&x, &y, croom); 930. mkstairs(x,y,(char)s->up, croom); 931. } 932. 933. /* 934. * Create an altar in a room. 935. */ 936. 937. static void 938. create_altar(a, croom) 939. altar *a; 940. struct mkroom *croom; 941. { 942. schar sproom,x,y; 943. aligntyp amask; 944. boolean croom_is_temple = TRUE; 945. 946. x = a->x; y = a->y; 947. 948. if (croom) { 949. get_free_room_loc(&x, &y, croom); 950. if (croom->rtype != TEMPLE) 951. croom_is_temple = FALSE; 952. } else { 953. get_location(&x, &y, DRY); 954. if (sproom = (schar) *in_rooms(x, y, TEMPLE)) 955. croom = &rooms[sproom - ROOMOFFSET]; 956. else 957. croom_is_temple = FALSE; 958. } 959. 960. a->x = x; 961. a->y = y; 962. 963. /* Is the alignment random ? 964. * If so, it's an 80% chance that the altar will be co-aligned. 965. * 966. * The alignment is encoded as amask values instead of alignment 967. * values to avoid conflicting with the rest of the encoding, 968. * shared by many other parts of the special level code. 969. */ 970. 971. amask = (a->align == -11) ? induced_align(80) : 972. (a->align < 0 ? ralign[-a->align-1] : a->align); 973. 974. levl[x][y].typ = ALTAR; 975. levl[x][y].altarmask = amask; 976. 977. if (a->shrine == -11) a->shrine = rn2(1); /* handle random case */ 978. 979. if (!croom_is_temple || !a->shrine) return; 980. 981. if (a->shrine) { /* Is it a shrine or sanctum? */ 982. priestini(&u.uz, croom, x, y, (a->shrine > 1)); 983. levl[x][y].altarmask |= AM_SHRINE; 984. level.flags.has_temple = TRUE; 985. } 986. } 987. 988. /* 989. * Create a gold pile in a room. 990. */ 991. 992. static void 993. create_gold(g,croom) 994. gold *g; 995. struct mkroom *croom; 996. { 997. schar x,y; 998. 999. x = g->x; y= g->y; 1000. if (croom) 1001. get_room_loc(&x, &y, croom); 1002. else 1003. get_location(&x, &y, DRY); 1004. 1005. if (g->amount == -1) 1006. g->amount = rnd(200); 1007. mkgold((long) g->amount, x, y); 1008. } 1009. 1010. /* 1011. * Create a feature (e.g a fountain) in a room. 1012. */ 1013. 1014. static void 1015. create_feature(fx, fy, croom, typ) 1016. int fx, fy; 1017. struct mkroom *croom; 1018. int typ; 1019. { 1020. schar x,y; 1021. int trycnt = 0; 1022. 1023. x = fx; y = fy; 1024. if (croom) { 1025. if (x < 0 && y < 0) 1026. do { 1027. x = -1; y = -1; 1028. get_room_loc(&x, &y, croom); 1029. } while (++trycnt <= 200 && occupied(x,y)); 1030. else 1031. get_room_loc(&x, &y, croom); 1032. if(trycnt > 200) 1033. return; 1034. } else { 1035. get_location(&x, &y, DRY); 1036. } 1037. levl[x][y].typ = typ; 1038. } 1039. 1040. /* 1041. * Search for a door in a room on a specified wall. 1042. */ 1043. 1044. static boolean 1045. search_door(croom,x,y,wall,cnt) 1046. struct mkroom *croom; 1047. xchar *x, *y; 1048. xchar wall; 1049. int cnt; 1050. { 1051. int dx, dy; 1052. int xx,yy; 1053. 1054. switch(wall) { 1055. case W_NORTH: 1056. dy = 0; dx = 1; 1057. xx = croom->lx; 1058. yy = croom->hy + 1; 1059. break; 1060. case W_SOUTH: 1061. dy = 0; dx = 1; 1062. xx = croom->lx; 1063. yy = croom->ly - 1; 1064. break; 1065. case W_EAST: 1066. dy = 1; dx = 0; 1067. xx = croom->hx + 1; 1068. yy = croom->ly; 1069. break; 1070. case W_WEST: 1071. dy = 1; dx = 0; 1072. xx = croom->lx - 1; 1073. yy = croom->ly; 1074. break; 1075. default: 1076. dx = dy = xx = yy = 0; 1077. panic("search_door: Bad wall!"); 1078. break; 1079. } 1080. while (xx <= croom->hx+1 && yy <= croom->hy+1) { 1081. if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) { 1082. *x = xx; 1083. *y = yy; 1084. if (cnt-- <= 0) 1085. return TRUE; 1086. } 1087. xx += dx; 1088. yy += dy; 1089. } 1090. return FALSE; 1091. } 1092. 1093. /* 1094. * Dig a corridor between two points. 1095. */ 1096. 1097. boolean 1098. dig_corridor(org,dest,nxcor,ftyp,btyp) 1099. coord org, dest; 1100. boolean nxcor; 1101. schar ftyp, btyp; 1102. { 1103. register int dx=0, dy=0, dix, diy, cct; 1104. register struct rm *crm; 1105. register int tx, ty, xx, yy; 1106. 1107. xx = org.x; yy = org.y; 1108. tx = dest.x; ty = dest.y; 1109. if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 || 1110. xx > COLNO-1 || tx > COLNO-1 || 1111. yy > ROWNO-1 || ty > ROWNO-1) { 1112. #ifdef DEBUG 1113. debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).", 1114. xx,yy,tx,ty); 1115. #endif 1116. return FALSE; 1117. } 1118. if (tx > xx) dx = 1; 1119. else if (ty > yy) dy = 1; 1120. else if (tx < xx) dx = -1; 1121. else dy = -1; 1122. 1123. xx -= dx; 1124. yy -= dy; 1125. cct = 0; 1126. while(xx != tx || yy != ty) { 1127. /* loop: dig corridor at [xx,yy] and find new [xx,yy] */ 1128. if(cct++ > 500 || (nxcor && !rn2(35))) 1129. return FALSE; 1130. 1131. xx += dx; 1132. yy += dy; 1133. 1134. if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1) 1135. return FALSE; /* impossible */ 1136. 1137. crm = &levl[xx][yy]; 1138. if(crm->typ == btyp) { 1139. if(ftyp != CORR || rn2(100)) { 1140. crm->typ = ftyp; 1141. if(nxcor && !rn2(50)) 1142. (void) mksobj_at(BOULDER, xx, yy, TRUE); 1143. } else { 1144. crm->typ = SCORR; 1145. } 1146. } else 1147. if(crm->typ != ftyp && crm->typ != SCORR) { 1148. /* strange ... */ 1149. return FALSE; 1150. } 1151. 1152. /* find next corridor position */ 1153. dix = abs(xx-tx); 1154. diy = abs(yy-ty); 1155. 1156. /* do we have to change direction ? */ 1157. if(dy && dix > diy) { 1158. register int ddx = (xx > tx) ? -1 : 1; 1159. 1160. crm = &levl[xx+ddx][yy]; 1161. if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) { 1162. dx = ddx; 1163. dy = 0; 1164. continue; 1165. } 1166. } else if(dx && diy > dix) { 1167. register int ddy = (yy > ty) ? -1 : 1; 1168. 1169. crm = &levl[xx][yy+ddy]; 1170. if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) { 1171. dy = ddy; 1172. dx = 0; 1173. continue; 1174. } 1175. } 1176. 1177. /* continue straight on? */ 1178. crm = &levl[xx+dx][yy+dy]; 1179. if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) 1180. continue; 1181. 1182. /* no, what must we do now?? */ 1183. if(dx) { 1184. dx = 0; 1185. dy = (ty < yy) ? -1 : 1; 1186. } else { 1187. dy = 0; 1188. dx = (tx < xx) ? -1 : 1; 1189. } 1190. crm = &levl[xx+dx][yy+dy]; 1191. if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) 1192. continue; 1193. dy = -dy; 1194. dx = -dx; 1195. } 1196. return TRUE; 1197. } 1198. 1199. /* 1200. * Disgusting hack: since special levels have their rooms filled before 1201. * sorting the rooms, we have to re-arrange the speed values upstairs_room 1202. * and dnstairs_room after the rooms have been sorted. On normal levels, 1203. * stairs don't get created until _after_ sorting takes place. 1204. */ 1205. static void 1206. fix_stair_rooms() 1207. { 1208. register i; 1209. register struct mkroom *croom; 1210. 1211. if(xdnstair && 1212. !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) && 1213. (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) { 1214. for(i=0; i < nroom; i++) { 1215. croom = &rooms[i]; 1216. if((croom->lx <= xdnstair && xdnstair <= croom->hx) && 1217. (croom->ly <= ydnstair && ydnstair <= croom->hy)) { 1218. dnstairs_room = croom; 1219. break; 1220. } 1221. } 1222. if(i == nroom) 1223. panic("Couldn't find dnstair room in fix_stair_rooms!"); 1224. } 1225. if(xupstair && 1226. !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) && 1227. (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) { 1228. for(i=0; i < nroom; i++) { 1229. croom = &rooms[i]; 1230. if((croom->lx <= xupstair && xupstair <= croom->hx) && 1231. (croom->ly <= yupstair && yupstair <= croom->hy)) { 1232. upstairs_room = croom; 1233. break; 1234. } 1235. } 1236. if(i == nroom) 1237. panic("Couldn't find upstair room in fix_stair_rooms!"); 1238. } 1239. } 1240. 1241. /* 1242. * Corridors always start from a door. But it can end anywhere... 1243. * Basically we search for door coordinates or for endpoints coordinates 1244. * (from a distance). 1245. */ 1246. 1247. static void 1248. create_corridor(c) 1249. corridor *c; 1250. { 1251. coord org, dest; 1252. 1253. if (c->src.room == -1) { 1254. sort_rooms(); 1255. fix_stair_rooms(); 1256. makecorridors(); 1257. return; 1258. } 1259. 1260. if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall, 1261. c->src.door)) 1262. return; 1263. 1264. if (c->dest.room != -1) { 1265. if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y, 1266. c->dest.wall, c->dest.door)) 1267. return; 1268. switch(c->src.wall) { 1269. case W_NORTH: org.y--; break; 1270. case W_SOUTH: org.y++; break; 1271. case W_WEST: org.x--; break; 1272. case W_EAST: org.x++; break; 1273. } 1274. switch(c->dest.wall) { 1275. case W_NORTH: dest.y--; break; 1276. case W_SOUTH: dest.y++; break; 1277. case W_WEST: dest.x--; break; 1278. case W_EAST: dest.x++; break; 1279. } 1280. (void) dig_corridor(org, dest, FALSE, CORR, STONE); 1281. } 1282. } 1283. 1284. 1285. /* 1286. * Fill a room (shop, zoo, etc...) with appropriate stuff. 1287. */ 1288. 1289. void 1290. fill_room(croom, prefilled) 1291. struct mkroom *croom; 1292. boolean prefilled; 1293. { 1294. if (!croom || croom->rtype == OROOM) 1295. return; 1296. 1297. if(prefilled) { 1298. switch(croom->rtype) { 1299. case COURT: 1300. level.flags.has_court = 1; 1301. break; 1302. #ifdef ARMY 1303. case BARRACKS: 1304. level.flags.has_barracks = 1; 1305. break; 1306. #endif 1307. case ZOO: 1308. level.flags.has_zoo = 1; 1309. break; 1310. case MORGUE: 1311. level.flags.has_morgue = 1; 1312. break; 1313. case SWAMP: 1314. level.flags.has_swamp = 1; 1315. break; 1316. case BEEHIVE: 1317. level.flags.has_beehive = 1; 1318. break; 1319. } 1320. return; 1321. } 1322. /* Vault ? */ 1323. if (croom->rtype == VAULT) { 1324. int x,y; 1325. for (x=croom->lx;x<=croom->hx;x++) 1326. for (y=croom->ly;y<=croom->hy;y++) 1327. mkgold((long)rn1(depth(&u.uz)*100, 51), x, y); 1328. return; 1329. } 1330. 1331. /* Shop ? */ 1332. if (croom->rtype >= SHOPBASE) { 1333. stock_room(croom->rtype - SHOPBASE, croom); 1334. return; 1335. } 1336. 1337. /* Zoo ? */ 1338. switch (croom->rtype) { 1339. case COURT: 1340. case ZOO: 1341. case BEEHIVE: 1342. case MORGUE: 1343. case BARRACKS: 1344. fill_zoo(croom); 1345. break; 1346. } 1347. } 1348. 1349. static void 1350. free_rooms(ro, n) 1351. room **ro; 1352. int n; 1353. { 1354. short j; 1355. room *r; 1356. 1357. while(n--) { 1358. r = ro[n]; 1359. Free(r->name); 1360. Free(r->parent); 1361. if (j = r->ndoor) { 1362. while(j--) 1363. Free(r->doors[j]); 1364. Free(r->doors); 1365. } 1366. if (j = r->ntrap) { 1367. while (j--) 1368. Free(r->traps[j]); 1369. Free(r->traps); 1370. } 1371. if (j = r->nmonster) { 1372. while (j--) { 1373. Free(r->monsters[j]->name); 1374. Free(r->monsters[j]->appear_as); 1375. Free(r->monsters[j]); 1376. } 1377. Free(r->monsters); 1378. } 1379. if (j = r->nobject) { 1380. while(j--) { 1381. Free(r->objects[j]->name); 1382. Free(r->objects[j]); 1383. } 1384. Free(r->objects); 1385. } 1386. if (j = r->nstair) { 1387. while(j--) 1388. Free(r->stairs[j]); 1389. Free(r->stairs); 1390. } 1391. if (j = r->naltar) { 1392. while (j--) 1393. Free(r->altars[j]); 1394. Free(r->altars); 1395. } 1396. if (j = r->ngold) { 1397. while(j--) 1398. Free(r->golds[j]); 1399. Free(r->golds); 1400. } 1401. if (j = r->nengraving) { 1402. while(j--) { 1403. Free(r->engravings[j]->e.text); 1404. Free(r->engravings[j]); 1405. } 1406. Free(r->engravings); 1407. } 1408. if (j = r->nfountain) { 1409. while(j--) 1410. Free(r->fountains[j]); 1411. Free(r->fountains); 1412. } 1413. if (j = r->nsink) { 1414. while(j--) 1415. Free(r->sinks[j]); 1416. Free(r->sinks); 1417. } 1418. if (j = r->npool) { 1419. while(j--) 1420. Free(r->pools[j]); 1421. Free(r->pools); 1422. } 1423. Free(r); 1424. } 1425. } 1426. 1427. static void 1428. build_room(r, pr) 1429. room *r, *pr; 1430. { 1431. boolean okroom; 1432. struct mkroom *aroom; 1433. short i; 1434. xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM; 1435. 1436. if(pr) { 1437. aroom = &subrooms[nsubroom]; 1438. okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h, 1439. rtype, r->rlit); 1440. } else { 1441. aroom = &rooms[nroom]; 1442. okroom = create_room(r->x, r->y, r->w, r->h, r->xalign, 1443. r->yalign, rtype, r->rlit); 1444. r->mkr = aroom; 1445. } 1446. 1447. if (okroom) { 1448. /* Create subrooms if necessary... */ 1449. for(i=0; i < r->nsubroom; i++) 1450. build_room(r->subrooms[i], r); 1451. /* And now we can fill the room! */ 1452. 1453. /* Priority to the stairs */ 1454. 1455. for(i=0; i <r->nstair; i++) 1456. create_stairs(r->stairs[i], aroom); 1457. 1458. /* Then to the various elements (sinks, etc..) */ 1459. for(i = 0; i<r->nsink; i++) 1460. create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK); 1461. for(i = 0; i<r->npool; i++) 1462. create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL); 1463. for(i = 0; i<r->nfountain; i++) 1464. create_feature(r->fountains[i]->x, r->fountains[i]->y, 1465. aroom, FOUNTAIN); 1466. for(i = 0; i<r->naltar; i++) 1467. create_altar(r->altars[i], aroom); 1468. for(i = 0; i<r->ndoor; i++) 1469. create_door(r->doors[i], aroom); 1470. 1471. /* The traps */ 1472. for(i = 0; i<r->ntrap; i++) 1473. create_trap(r->traps[i], aroom); 1474. 1475. /* The monsters */ 1476. for(i = 0; i<r->nmonster; i++) 1477. create_monster(r->monsters[i], aroom); 1478. 1479. /* The objects */ 1480. for(i = 0; i<r->nobject; i++) 1481. create_object(r->objects[i], aroom); 1482. 1483. /* The gold piles */ 1484. for(i = 0; i<r->ngold; i++) 1485. create_gold(r->golds[i], aroom); 1486. 1487. /* The engravings */ 1488. for(i = 0; i<r->nengraving; i++) { 1489. schar xx, yy; 1490. 1491. xx = r->engravings[i]->x; 1492. yy = r->engravings[i]->y; 1493. get_room_loc(&xx, &yy, aroom); 1494. make_engr_at(xx, yy, r->engravings[i]->e.text, 1495. 0L, r->engravings[i]->etype); 1496. } 1497. #ifdef SPECIALIZATION 1498. topologize(aroom,FALSE); /* set roomno */ 1499. #else 1500. topologize(aroom); /* set roomno */ 1501. #endif 1502. /* MRS - 07/04/91 - This is temporary but should result 1503. * in proper filling of shops, etc. 1504. * DLC - this can fail if corridors are added to this room 1505. * at a later point. Currently no good way to fix this. 1506. */ 1507. if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE); 1508. } 1509. } 1510. 1511. /* 1512. * set lighting in a region that will not become a room. 1513. */ 1514. static void 1515. light_region(tmpregion) 1516. region *tmpregion; 1517. { 1518. register boolean litstate = tmpregion->rlit ? 1 : 0; 1519. register int hiy = tmpregion->y2; 1520. register int x, y; 1521. register struct rm *lev; 1522. int lowy = tmpregion->y1; 1523. int lowx = tmpregion->x1, hix = tmpregion->x2; 1524. 1525. if(litstate) { 1526. /* adjust region size for walls, but only if lighted */ 1527. lowx = max(lowx-1,1); 1528. hix = min(hix+1,COLNO-1); 1529. lowy = max(lowy-1,0); 1530. hiy = min(hiy+1, ROWNO-1); 1531. } 1532. for(x = lowx; x <= hix; x++) { 1533. lev = &levl[x][lowy]; 1534. for(y = lowy; y <= hiy; y++) 1535. lev++->lit = litstate; 1536. } 1537. } 1538. 1539. /* initialization common to all special levels */ 1540. static void 1541. load_common_data(fd, typ) 1542. FILE *fd; 1543. int typ; 1544. { 1545. uchar n; 1546. long lev_flags; 1547. int i; 1548. 1549. { 1550. aligntyp atmp; 1551. /* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */ 1552. i = rn2(3); atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp; 1553. if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; } 1554. } 1555. 1556. level.flags.is_maze_lev = typ == SP_LEV_MAZE; 1557. 1558. /* free up old level regions */ 1559. if(num_lregions) { 1560. for(i=0; i<num_lregions; i++) 1561. if(lregions[i].rname) Free(lregions[i].rname); 1562. Free(lregions); 1563. num_lregions = 0; 1564. } 1565. lregions = (lev_region *) 0; 1566. 1567. /* Read the level initialization data */ 1568. Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd); 1569. if(init_lev.init_present) { 1570. if(init_lev.lit < 0) 1571. init_lev.lit = rn2(2); 1572. mkmap(&init_lev); 1573. } 1574. 1575. /* Read the per level flags */ 1576. Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd); 1577. if (lev_flags & NOTELEPORT) 1578. level.flags.noteleport = 1; 1579. if (lev_flags & HARDFLOOR) 1580. level.flags.hardfloor = 1; 1581. if (lev_flags & NOMMAP) 1582. level.flags.nommap = 1; 1583. if (lev_flags & SHORTSIGHTED) 1584. level.flags.shortsighted = 1; 1585. 1586. /* Read message */ 1587. Fread((genericptr_t) &n, 1, sizeof(n), fd); 1588. if (n) { 1589. lev_message = (char *) alloc(n + 1); 1590. Fread((genericptr_t) lev_message, 1, (int) n, fd); 1591. lev_message[n] = 0; 1592. } 1593. } 1594. 1595. static boolean 1596. load_rooms(fd) 1597. FILE *fd; 1598. { 1599. xchar nrooms; 1600. char n; 1601. short size; 1602. corridor tmpcor; 1603. room** tmproom; 1604. int i, j, ncorr; 1605. 1606. load_common_data(fd, SP_LEV_ROOMS); 1607. 1608. Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */ 1609. if (n) { 1610. Fread((genericptr_t)robjects, sizeof(*robjects), n, fd); 1611. sp_lev_shuffle(robjects, (char *)0, (int)n); 1612. } 1613. 1614. Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */ 1615. if (n) { 1616. Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd); 1617. sp_lev_shuffle(rmonst, (char *)0, (int)n); 1618. } 1619. 1620. Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd); 1621. /* Number of rooms to read */ 1622. tmproom = NewTab(room,nrooms); 1623. for (i=0;i<nrooms;i++) { 1624. room *r; 1625. 1626. r = tmproom[i] = New(room); 1627. 1628. /* Let's see if this room has a name */ 1629. Fread((genericptr_t) &size, 1, sizeof(size), fd); 1630. if (size > 0) { /* Yup, it does! */ 1631. r->name = (char *) alloc(size + 1); 1632. Fread((genericptr_t) r->name, 1, size, fd); 1633. r->name[size] = 0; 1634. } else 1635. r->name = (char *) 0; 1636. 1637. /* Let's see if this room has a parent */ 1638. Fread((genericptr_t) &size, 1, sizeof(size), fd); 1639. if (size > 0) { /* Yup, it does! */ 1640. r->parent = (char *) alloc(size + 1); 1641. Fread((genericptr_t) r->parent, 1, size, fd); 1642. r->parent[size] = 0; 1643. } else 1644. r->parent = (char *) 0; 1645. 1646. Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd); 1647. /* x pos on the grid (1-5) */ 1648. Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd); 1649. /* y pos on the grid (1-5) */ 1650. Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd); 1651. /* width of the room */ 1652. Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd); 1653. /* height of the room */ 1654. Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd); 1655. /* horizontal alignment */ 1656. Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd); 1657. /* vertical alignment */ 1658. Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd); 1659. /* type of room (zoo, shop, etc.) */ 1660. Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd); 1661. /* chance of room being special. */ 1662. Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd); 1663. /* lit or not ? */ 1664. Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd); 1665. /* to be filled? */ 1666. r->nsubroom= 0; 1667. 1668. /* read the doors */ 1669. Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd); 1670. if(n = r->ndoor) 1671. r->doors = NewTab(room_door, n); 1672. while(n--) { 1673. r->doors[n] = New(room_door); 1674. Fread((genericptr_t) r->doors[n], 1, 1675. sizeof(room_door), fd); 1676. } 1677. 1678. /* read the traps */ 1679. Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd); 1680. if(n = r->ntrap) 1681. r->traps = NewTab(trap, n); 1682. while(n--) { 1683. r->traps[n] = New(trap); 1684. Fread((genericptr_t) r->traps[n], 1, sizeof(trap), fd); 1685. } 1686. 1687. /* read the monsters */ 1688. Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd); 1689. if(n = r->nmonster) 1690. r->monsters = NewTab(monster, n); 1691. while(n--) { 1692. r->monsters[n] = New(monster); 1693. Fread((genericptr_t) r->monsters[n], 1, 1694. sizeof(monster), fd); 1695. Fread((genericptr_t) &size, sizeof(size), 1, fd); 1696. if (size) { 1697. r->monsters[n]->name= (char *) alloc(size + 1); 1698. Fread((genericptr_t)r->monsters[n]->name, 1699. 1, size, fd); 1700. r->monsters[n]->name[size] = 0; 1701. } else 1702. r->monsters[n]->name = (char *) 0; 1703. 1704. Fread((genericptr_t) &size, sizeof(size), 1, fd); 1705. if (size) { 1706. r->monsters[n]->appear_as= 1707. (char *) alloc(size + 1); 1708. Fread((genericptr_t)r->monsters[n]->appear_as, 1709. 1, size, fd); 1710. r->monsters[n]->appear_as[size] = 0; 1711. } else 1712. r->monsters[n]->appear_as = (char *) 0; 1713. } 1714. 1715. /* read the objects */ 1716. Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd); 1717. if(n = r->nobject) 1718. r->objects = NewTab(object, n); 1719. while (n--) { 1720. r->objects[n] = New(object); 1721. Fread((genericptr_t) r->objects[n], 1, 1722. sizeof(object), fd); 1723. Fread((genericptr_t) &size, 1, sizeof(size), fd); 1724. if (size) { 1725. r->objects[n]->name = (char *) alloc(size + 1); 1726. Fread((genericptr_t)r->objects[n]->name, 1727. 1, size, fd); 1728. r->objects[n]->name[size] = 0; 1729. } else 1730. r->objects[n]->name = (char *) 0; 1731. } 1732. 1733. /* read the stairs */ 1734. Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd); 1735. if (n = r->nstair) 1736. r->stairs = NewTab(stair, n); 1737. while (n--) { 1738. r->stairs[n] = New(stair); 1739. Fread((genericptr_t) r->stairs[n], 1, 1740. sizeof(stair), fd); 1741. } 1742. 1743. /* read the altars */ 1744. Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd); 1745. if (n = r->naltar) 1746. r->altars = NewTab(altar, n); 1747. while (n--) { 1748. r->altars[n] = New(altar); 1749. Fread((genericptr_t) r->altars[n], 1, 1750. sizeof(altar), fd); 1751. } 1752. 1753. /* read the gold piles */ 1754. Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd); 1755. if (n = r->ngold) 1756. r->golds = NewTab(gold, n); 1757. while (n--) { 1758. r->golds[n] = New(gold); 1759. Fread((genericptr_t) r->golds[n], 1, sizeof(gold), fd); 1760. } 1761. 1762. /* read the engravings */ 1763. Fread((genericptr_t) &r->nengraving, 1, 1764. sizeof(r->nengraving), fd); 1765. if (n = r->nengraving) 1766. r->engravings = NewTab(engraving,n); 1767. while(n--) { 1768. r->engravings[n] = New(engraving); 1769. Fread((genericptr_t) r->engravings[n], 1770. 1, sizeof *r->engravings[n], fd); 1771. size = r->engravings[n]->e.length; 1772. r->engravings[n]->e.text = (char *) alloc(size+1); 1773. Fread((genericptr_t) r->engravings[n]->e.text, 1774. 1, size, fd); 1775. r->engravings[n]->e.text[size] = '\0'; 1776. } 1777. 1778. /* read the fountains */ 1779. Fread((genericptr_t) &r->nfountain, 1, 1780. sizeof(r->nfountain), fd); 1781. if (n = r->nfountain) 1782. r->fountains = NewTab(fountain, n); 1783. while (n--) { 1784. r->fountains[n] = New(fountain); 1785. Fread((genericptr_t) r->fountains[n], 1, 1786. sizeof(fountain), fd); 1787. } 1788. 1789. /* read the sinks */ 1790. Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd); 1791. if (n = r->nsink) 1792. r->sinks = NewTab(sink, n); 1793. while (n--) { 1794. r->sinks[n] = New(sink); 1795. Fread((genericptr_t) r->sinks[n], 1, sizeof(sink), fd); 1796. } 1797. 1798. /* read the pools */ 1799. Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd); 1800. if (n = r->npool) 1801. r->pools = NewTab(pool,n); 1802. while (n--) { 1803. r->pools[n] = New(pool); 1804. Fread((genericptr_t) r->pools[n], 1, sizeof(pool), fd); 1805. } 1806. 1807. } 1808. 1809. /* Now that we have loaded all the rooms, search the 1810. * subrooms and create the links. 1811. */ 1812. 1813. for (i = 0; i<nrooms; i++) 1814. if (tmproom[i]->parent) { 1815. /* Search the parent room */ 1816. for(j=0; j<nrooms; j++) 1817. if (tmproom[j]->name && !strcmp(tmproom[j]->name, 1818. tmproom[i]->parent)) { 1819. n = tmproom[j]->nsubroom++; 1820. tmproom[j]->subrooms[n] = tmproom[i]; 1821. break; 1822. } 1823. } 1824. 1825. /* 1826. * Create the rooms now... 1827. */ 1828. 1829. for (i=0; i < nrooms; i++) 1830. if(!tmproom[i]->parent) 1831. build_room(tmproom[i], (room *) 0); 1832. 1833. free_rooms(tmproom, nrooms); 1834. 1835. /* read the corridors */ 1836. 1837. Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd); 1838. for (i=0; i<ncorr; i++) { 1839. Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd); 1840. create_corridor(&tmpcor); 1841. } 1842. 1843. return TRUE; 1844. } 1845. 1846. /* 1847. * Select a random coordinate in the maze. 1848. * 1849. * We want a place not 'touched' by the loader. That is, a place in 1850. * the maze outside every part of the special level. 1851. */ 1852. 1853. static void 1854. maze1xy(m) 1855. coord *m; 1856. { 1857. do { 1858. m->x = rn1(x_maze_max - 3, 3); 1859. m->y = rn1(y_maze_max - 3, 3); 1860. } while (!(m->x % 2) || !(m->y % 2) || Map[m->x][m->y]); 1861. } 1862. 1863. /* 1864. * The Big Thing: special maze loader 1865. * 1866. * Could be cleaner, but it works. 1867. */ 1868. 1869. static boolean 1870. load_maze(fd) 1871. FILE *fd; 1872. { 1873. xchar x, y, typ; 1874. boolean prefilled; 1875. 1876. char n, numpart = 0; 1877. xchar nwalk = 0, nwalk_sav; 1878. short filling; 1879. char halign, valign; 1880. 1881. int xi, yi, dir; 1882. coord mm; 1883. int mapcount, mapcountmax, mapfact; 1884. 1885. lev_region tmplregion; 1886. region tmpregion; 1887. door tmpdoor; 1888. trap tmptrap; 1889. monster tmpmons; 1890. object tmpobj; 1891. drawbridge tmpdb; 1892. walk tmpwalk; 1893. digpos tmpdig; 1894. lad tmplad; 1895. stair tmpstair, prevstair; 1896. altar tmpaltar; 1897. gold tmpgold; 1898. fountain tmpfountain; 1899. engraving tmpengraving; 1900. xchar mustfill[(MAXNROFROOMS+1)*2]; 1901. struct trap *badtrap; 1902. boolean has_bounds; 1903. 1904. load_common_data(fd, SP_LEV_MAZE); 1905. 1906. /* Initialize map */ 1907. Fread((genericptr_t) &filling, 1, sizeof(filling), fd); 1908. if(!init_lev.init_present) /* don't init if mkmap() has been called */ 1909. for(x = 2; x <= x_maze_max; x++) 1910. for(y = 0; y <= y_maze_max; y++) 1911. if (filling == -1) { 1912. #ifndef WALLIFIED_MAZE 1913. levl[x][y].typ = STONE; 1914. #else 1915. levl[x][y].typ = 1916. (y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL; 1917. #endif 1918. Map[x][y] = 0; 1919. } else { 1920. levl[x][y].typ = filling; 1921. Map[x][y] = 0; 1922. } 1923. 1924. /* Start reading the file */ 1925. Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd); 1926. /* Number of parts */ 1927. if (!numpart || numpart > 9) 1928. panic("load_maze error: numpart = %d", (int) numpart); 1929. 1930. while (numpart--) { 1931. Fread((genericptr_t) &halign, 1, sizeof(halign), fd); 1932. /* Horizontal alignment */ 1933. Fread((genericptr_t) &valign, 1, sizeof(valign), fd); 1934. /* Vertical alignment */ 1935. Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd); 1936. /* size in X */ 1937. Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd); 1938. /* size in Y */ 1939. switch((int) halign) { 1940. case LEFT: xstart = 3; break; 1941. case H_LEFT: xstart = 2+((x_maze_max-2-xsize)/4); break; 1942. case CENTER: xstart = 2+((x_maze_max-2-xsize)/2); break; 1943. case H_RIGHT: xstart = 2+((x_maze_max-2-xsize)*3/4); break; 1944. case RIGHT: xstart = x_maze_max-xsize-1; break; 1945. } 1946. switch((int) valign) { 1947. case TOP: ystart = 3; break; 1948. case CENTER: ystart = 2+((y_maze_max-2-ysize)/2); break; 1949. case BOTTOM: ystart = y_maze_max-ysize-1; break; 1950. } 1951. if (!(xstart % 2)) xstart++; 1952. if (!(ystart % 2)) ystart++; 1953. if ((ystart < 0) || (ystart + ysize > ROWNO)) { 1954. /* try to move the start a bit */ 1955. ystart += (ystart > 0) ? -2 : 2; 1956. if(ysize == ROWNO) ystart = 0; 1957. if(ystart < 0 || ystart + ysize > ROWNO) 1958. panic("reading special level with ysize to large"); 1959. } 1960. 1961. /* 1962. * If any CROSSWALLs are found, must change to ROOM after REGION's 1963. * are laid out. CROSSWALLS are used to specify "invisible" 1964. * boundaries where DOOR syms look bad or aren't desirable. 1965. */ 1966. has_bounds = FALSE; 1967. 1968. if(init_lev.init_present && xsize <= 1 && ysize <= 1) { 1969. xstart = 1; 1970. ystart = 0; 1971. xsize = COLNO-1; 1972. ysize = ROWNO; 1973. } else { 1974. /* Load the map */ 1975. for(y = ystart; y < ystart+ysize; y++) 1976. for(x = xstart; x < xstart+xsize; x++) { 1977. levl[x][y].typ = (schar) fgetc(fd); 1978. levl[x][y].lit = FALSE; 1979. /* 1980. * Note: Even though levl[x][y].typ is type schar, 1981. * lev_comp.y saves it as type char. Since schar != char 1982. * all the time we must make this exception or hack 1983. * through lev_comp.y to fix. 1984. */ 1985. 1986. /* 1987. * Set secret doors to closed (why not trapped too?). Set 1988. * the horizontal bit. 1989. */ 1990. if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) { 1991. if(levl[x][y].typ == SDOOR) 1992. levl[x][y].doormask = D_CLOSED; 1993. /* 1994. * If there is a wall to the left that connects to a 1995. * (secret) door, then it is horizontal. This does 1996. * not allow (secret) doors to be corners of rooms. 1997. */ 1998. if (x != xstart && (IS_WALL(levl[x-1][y].typ) || 1999. levl[x-1][y].horizontal)) 2000. levl[x][y].horizontal = 1; 2001. } else if(levl[x][y].typ == HWALL) 2002. levl[x][y].horizontal = 1; 2003. else if(levl[x][y].typ == LAVAPOOL) 2004. levl[x][y].lit = 1; 2005. else if(levl[x][y].typ == CROSSWALL) 2006. has_bounds = TRUE; 2007. Map[x][y] = 1; 2008. } 2009. } 2010. 2011. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2012. /* Number of level regions */ 2013. if(n) { 2014. if(num_lregions) { 2015. /* realloc the lregion space to add the new ones */ 2016. /* don't really free it up until the whole level is done */ 2017. lev_region *newl = (lev_region *) alloc(sizeof(lev_region) * 2018. (n+num_lregions)); 2019. (void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions, 2020. sizeof(lev_region) * num_lregions); 2021. Free(lregions); 2022. num_lregions += n; 2023. lregions = newl; 2024. } else { 2025. num_lregions = n; 2026. lregions = (lev_region *) alloc(sizeof(lev_region) * n); 2027. } 2028. } 2029. 2030. while(n--) { 2031. Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd); 2032. if(tmplregion.rname) { 2033. char len; 2034. 2035. Fread((genericptr_t) &len, sizeof(len), 1, fd); 2036. tmplregion.rname = (char *) alloc(len + 1); 2037. Fread((genericptr_t) tmplregion.rname, len, 1, fd); 2038. tmplregion.rname[len] = 0; 2039. } 2040. if(!tmplregion.in_islev) { 2041. get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1, 2042. DRY|WET); 2043. get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2, 2044. DRY|WET); 2045. } 2046. if(!tmplregion.del_islev) { 2047. get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1, 2048. DRY|WET); 2049. get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2, 2050. DRY|WET); 2051. } 2052. lregions[n] = tmplregion; 2053. } 2054. 2055. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2056. /* Random objects */ 2057. if(n) { 2058. Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd); 2059. sp_lev_shuffle(robjects, (char *)0, (int)n); 2060. } 2061. 2062. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2063. /* Random locations */ 2064. if(n) { 2065. Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd); 2066. Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd); 2067. sp_lev_shuffle(rloc_x, rloc_y, (int)n); 2068. } 2069. 2070. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2071. /* Random monsters */ 2072. if(n) { 2073. Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd); 2074. sp_lev_shuffle(rmonst, (char *)0, (int)n); 2075. } 2076. 2077. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2078. /* Number of subrooms */ 2079. 2080. (void) memset((genericptr_t)mustfill, 0, sizeof(mustfill)); 2081. 2082. while(n--) { 2083. register struct mkroom *troom; 2084. 2085. Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd); 2086. 2087. if(tmpregion.rtype > MAXRTYPE) { 2088. tmpregion.rtype -= MAXRTYPE+1; 2089. prefilled = TRUE; 2090. } else 2091. prefilled = FALSE; 2092. 2093. if(tmpregion.rlit < 0) 2094. tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) 2095. ? TRUE : FALSE; 2096. 2097. get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET); 2098. get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET); 2099. 2100. if (((tmpregion.rtype == OROOM) && !tmpregion.rirreg) || 2101. (nroom >= MAXNROFROOMS)) { 2102. if(tmpregion.rtype != OROOM || tmpregion.rirreg) 2103. impossible("Too many rooms on new level!"); 2104. light_region(&tmpregion); 2105. continue; 2106. } 2107. 2108. troom = &rooms[nroom]; 2109. 2110. /* mark rooms that must be filled, but do it later */ 2111. if (tmpregion.rtype != OROOM) 2112. mustfill[nroom] = (prefilled ? 2 : 1); 2113. 2114. if(tmpregion.rirreg) { 2115. min_rx = max_rx = tmpregion.x1; 2116. min_ry = max_ry = tmpregion.y1; 2117. flood_fill_rm(tmpregion.x1, tmpregion.y1, 2118. nroom+ROOMOFFSET, tmpregion.rlit, TRUE); 2119. add_room(min_rx, min_ry, max_rx, max_ry, 2120. FALSE, tmpregion.rtype, TRUE); 2121. troom->rlit = tmpregion.rlit; 2122. troom->irregular = TRUE; 2123. } else { 2124. add_room(tmpregion.x1, tmpregion.y1, 2125. tmpregion.x2, tmpregion.y2, 2126. tmpregion.rlit, tmpregion.rtype, TRUE); 2127. #ifdef SPECIALIZATION 2128. topologize(troom,FALSE); /* set roomno */ 2129. #else 2130. topologize(troom); /* set roomno */ 2131. #endif 2132. } 2133. } 2134. 2135. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2136. /* Number of doors */ 2137. while(n--) { 2138. struct mkroom *croom = &rooms[0]; 2139. 2140. Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd); 2141. 2142. x = tmpdoor.x; y = tmpdoor.y; 2143. typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask; 2144. 2145. get_location(&x, &y, DRY); 2146. if(levl[x][y].typ != SDOOR) 2147. levl[x][y].typ = DOOR; 2148. else { 2149. if(typ < D_CLOSED) 2150. typ = D_CLOSED; /* force it to be closed */ 2151. } 2152. levl[x][y].doormask = typ; 2153. 2154. /* Now the complicated part, list it with each subroom */ 2155. /* The dog move and mail daemon routines use this */ 2156. while(croom->hx >= 0 && doorindex < DOORMAX) { 2157. if(croom->hx >= x-1 && croom->lx <= x+1 && 2158. croom->hy >= y-1 && croom->ly <= y+1) { 2159. /* Found it */ 2160. add_door(x, y, croom); 2161. } 2162. croom++; 2163. } 2164. } 2165. 2166. /* now that we have rooms _and_ associated doors, fill the rooms */ 2167. for(n = 0; n < SIZE(mustfill); n++) 2168. if(mustfill[n]) 2169. fill_room(&rooms[n], (mustfill[n] == 2)); 2170. 2171. /* if special boundary syms (CROSSWALL) in map, remove them now */ 2172. if(has_bounds) { 2173. for(x = xstart; x < xstart+xsize; x++) 2174. for(y = ystart; y < ystart+ysize; y++) 2175. if(levl[x][y].typ == CROSSWALL) 2176. levl[x][y].typ = ROOM; 2177. } 2178. 2179. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2180. /* Number of traps */ 2181. while(n--) { 2182. Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd); 2183. 2184. create_trap(&tmptrap, (struct mkroom *)0); 2185. } 2186. 2187. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2188. /* Number of monsters */ 2189. while(n--) { 2190. short size; 2191. 2192. Fread((genericptr_t) &tmpmons, 1, sizeof(tmpmons), fd); 2193. Fread((genericptr_t) &size, 1, sizeof(size), fd); 2194. if (size) { 2195. tmpmons.name = (char *) alloc(size + 1); 2196. Fread((genericptr_t) tmpmons.name, 1, size, fd); 2197. tmpmons.name[size] = 0; 2198. } else 2199. tmpmons.name = (char *) 0; 2200. Fread((genericptr_t) &size, 1, sizeof(size), fd); 2201. if (size) { 2202. tmpmons.appear_as = (char *) alloc(size + 1); 2203. Fread((genericptr_t) tmpmons.appear_as, 1, size, fd); 2204. tmpmons.appear_as[size] = 0; 2205. } else 2206. tmpmons.appear_as = (char *) 0; 2207. 2208. create_monster(&tmpmons, (struct mkroom *)0); 2209. 2210. if (tmpmons.name) 2211. free((genericptr_t) tmpmons.name); 2212. if (tmpmons.appear_as) 2213. free((genericptr_t) tmpmons.appear_as); 2214. } 2215. 2216. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2217. /* Number of objects */ 2218. while(n--) { 2219. short size; 2220. 2221. Fread((genericptr_t) &tmpobj, 1, sizeof(object), fd); 2222. Fread((genericptr_t) &size, 1, sizeof(size), fd); 2223. if (size) { 2224. tmpobj.name = (char *) alloc(size + 1); 2225. Fread((genericptr_t) tmpobj.name, 1, size, fd); 2226. tmpobj.name[size] = 0; 2227. } else 2228. tmpobj.name = (char *) 0; 2229. 2230. create_object(&tmpobj, (struct mkroom *)0); 2231. 2232. if (size) 2233. free((genericptr_t) tmpobj.name); 2234. } 2235. 2236. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2237. /* Number of drawbridges */ 2238. while(n--) { 2239. Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd); 2240. 2241. x = tmpdb.x; y = tmpdb.y; 2242. get_location(&x, &y, DRY|WET); 2243. 2244. if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open)) 2245. impossible("Cannot create drawbridge."); 2246. } 2247. 2248. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2249. /* Number of mazewalks */ 2250. while(n--) { 2251. Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd); 2252. 2253. get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET); 2254. 2255. walklist[nwalk++] = tmpwalk; 2256. } 2257. 2258. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2259. /* Number of non_diggables */ 2260. while(n--) { 2261. Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd); 2262. 2263. get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET); 2264. get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET); 2265. 2266. make_walls_nondiggable(tmpdig.x1, tmpdig.y1, 2267. tmpdig.x2, tmpdig.y2); 2268. } 2269. 2270. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2271. /* Number of ladders */ 2272. while(n--) { 2273. Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd); 2274. 2275. x = tmplad.x; y = tmplad.y; 2276. get_location(&x, &y, DRY); 2277. 2278. levl[x][y].typ = LADDER; 2279. if (tmplad.up == 1) { 2280. xupladder = x; yupladder = y; 2281. levl[x][y].ladder = LA_UP; 2282. } else { 2283. xdnladder = x; ydnladder = y; 2284. levl[x][y].ladder = LA_DOWN; 2285. } 2286. } 2287. 2288. prevstair.x = prevstair.y = 0; 2289. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2290. /* Number of stairs */ 2291. while(n--) { 2292. Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd); 2293. 2294. xi = 0; 2295. do { 2296. x = tmpstair.x; y = tmpstair.y; 2297. get_location(&x, &y, DRY); 2298. } while(prevstair.x && xi++ < 100 && 2299. distmin(x,y,prevstair.x,prevstair.y) <= 8); 2300. if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap); 2301. mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0); 2302. prevstair.x = x; 2303. prevstair.y = y; 2304. } 2305. 2306. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2307. /* Number of altars */ 2308. while(n--) { 2309. Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd); 2310. 2311. create_altar(&tmpaltar, (struct mkroom *)0); 2312. } 2313. 2314. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2315. /* Number of gold pile */ 2316. while (n--) { 2317. Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd); 2318. 2319. create_gold(&tmpgold, (struct mkroom *)0); 2320. } 2321. 2322. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2323. /* Number of engravings */ 2324. while(n--) { 2325. int size; 2326. Fread((genericptr_t) &tmpengraving, 1, 2327. sizeof(tmpengraving), fd); 2328. size = tmpengraving.e.length; 2329. tmpengraving.e.text = (char *) alloc(size+1); 2330. Fread((genericptr_t) tmpengraving.e.text, 1, size, fd); 2331. tmpengraving.e.text[size] = '\0'; 2332. 2333. x = tmpengraving.x; y = tmpengraving.y; 2334. get_location(&x, &y, DRY); 2335. make_engr_at(x, y, tmpengraving.e.text, 0L, tmpengraving.etype); 2336. free((genericptr_t) tmpengraving.e.text); 2337. } 2338. 2339. Fread((genericptr_t) &n, 1, sizeof(n), fd); 2340. /* Number of fountains */ 2341. while (n--) { 2342. Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd); 2343. 2344. create_feature(tmpfountain.x, tmpfountain.y, 2345. (struct mkroom *)0, FOUNTAIN); 2346. } 2347. } 2348. 2349. nwalk_sav = nwalk; 2350. while(nwalk--) { 2351. xi = walklist[nwalk].x; 2352. yi = walklist[nwalk].y; 2353. dir = walklist[nwalk].dir; 2354. 2355. move(&xi, &yi, dir); 2356. x = xi; 2357. y = yi; 2358. 2359. if(!IS_DOOR(levl[x][y].typ)) { 2360. #ifndef WALLIFIED_MAZE 2361. levl[x][y].typ = CORR; 2362. #else 2363. levl[x][y].typ = ROOM; 2364. #endif 2365. levl[x][y].flags = 0; 2366. } 2367. 2368. /* 2369. * We must be sure that the parity of the coordinates for 2370. * walkfrom() is odd. But we must also take into account 2371. * what direction was chosen. 2372. */ 2373. if(!(x % 2)) { 2374. if (dir == W_EAST) 2375. x++; 2376. else 2377. x--; 2378. 2379. /* no need for IS_DOOR check; out of map bounds */ 2380. #ifndef WALLIFIED_MAZE 2381. levl[x][y].typ = CORR; 2382. #else 2383. levl[x][y].typ = ROOM; 2384. #endif 2385. levl[x][y].flags = 0; 2386. } 2387. 2388. if (!(y % 2)) 2389. if (dir == W_SOUTH) 2390. y++; 2391. else 2392. y--; 2393. 2394. walkfrom(x, y); 2395. } 2396. wallification(1, 0, COLNO-1, ROWNO-1); 2397. 2398. /* 2399. * If there's a significant portion of maze unused by the special level, 2400. * we don't want it empty. 2401. * 2402. * Makes the number of traps, monsters, etc. proportional 2403. * to the size of the maze. 2404. */ 2405. mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2); 2406. 2407. for(x = 2; x < x_maze_max; x++) 2408. for(y = 0; y < y_maze_max; y++) 2409. if(Map[x][y]) mapcount--; 2410. 2411. if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) { 2412. mapfact = (int) ((mapcount * 100L) / mapcountmax); 2413. for(x = rnd((int) (20 * mapfact) / 100); x; x--) { 2414. maze1xy(&mm); 2415. (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS, 2416. mm.x, mm.y, TRUE); 2417. } 2418. for(x = rnd((int) (12 * mapfact) / 100); x; x--) { 2419. maze1xy(&mm); 2420. (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE); 2421. } 2422. maze1xy(&mm); 2423. (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y); 2424. for(x = rnd((int) (12 * mapfact) / 100); x; x--) { 2425. maze1xy(&mm); 2426. (void) makemon((struct permonst *) 0, mm.x, mm.y); 2427. } 2428. for(x = rn2((int) (15 * mapfact) / 100); x; x--) { 2429. maze1xy(&mm); 2430. mkgold(0L,mm.x,mm.y); 2431. } 2432. for(x = rn2((int) (15 * mapfact) / 100); x; x--) { 2433. int trytrap = rndtrap(); 2434. 2435. maze1xy(&mm); 2436. if (is_pool(mm.x,mm.y)) continue; 2437. if (sobj_at(BOULDER, mm.x, mm.y)) 2438. while ((trytrap == PIT) || (trytrap == SPIKED_PIT)) 2439. trytrap = rndtrap(); 2440. (void) maketrap(mm.x, mm.y, trytrap); 2441. } 2442. } 2443. return TRUE; 2444. } 2445. 2446. /* 2447. * General loader 2448. */ 2449. 2450. boolean 2451. load_special(name) 2452. const char *name; 2453. { 2454. FILE *fd; 2455. boolean result; 2456. char c; 2457. 2458. fd = fopen_datafile(name, RDMODE); 2459. if (!fd) return FALSE; 2460. 2461. Fread((genericptr_t) &c, 1, sizeof(c), fd); /* c Header */ 2462. 2463. switch (c) { 2464. case SP_LEV_ROOMS: 2465. result = load_rooms(fd); 2466. break; 2467. case SP_LEV_MAZE: 2468. result = load_maze(fd); 2469. break; 2470. default: /* ??? */ 2471. result = FALSE; 2472. } 2473. (void)fclose(fd); 2474. return result; 2475. } 2476. 2477. /*sp_lev.c*/