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