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