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