Difference between revisions of "Source:SLASH'EM 0.0.7E7F2/sp lev.c"
Jump to navigation
Jump to search
Kernigh bot (talk | contribs) m (SLASH'EM 0.0.7E7F2/sp lev.c moved to Source:SLASH'EM 0.0.7E7F2/sp lev.c: Robot: moved page) |
m (Change particular-line instructions to our Source: filename. Fix wording on "source code for vanilla nethack".) |
||
Line 1: | Line 1: | ||
− | Below is the full text to '''sp_lev.c''' from the [[SLASH'EM 0.0.7E7F2 source code|source code]] of [[SLASH'EM 0.0.7E7F2]]. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/sp_lev.c#line123|<nowiki>[[SLASH'EM 0.0.7E7F2/sp_lev.c#line123]]</nowiki>]], for example. | + | Below is the full text to '''sp_lev.c''' from the [[SLASH'EM 0.0.7E7F2 source code|source code]] of [[SLASH'EM 0.0.7E7F2]]. To link to a particular line, write [[Source:SLASH'EM 0.0.7E7F2/sp_lev.c#line123|<nowiki>[[Source:SLASH'EM 0.0.7E7F2/sp_lev.c#line123]]</nowiki>]], for example. |
− | + | Source code for vanilla NetHack is at [[Source code]]. | |
Latest revision as of 02:31, 29 June 2024
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 [[Source:SLASH'EM 0.0.7E7F2/sp_lev.c#line123]], for example.
Source code for vanilla NetHack is at Source code.
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)sp_lev.c 3.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 <r->nstair; i++) 1752. create_stairs(r->stairs[i], aroom); 1753. 1754. /* Then to the various elements (sinks, etc..) */ 1755. for(i = 0; i<r->nsink; i++) 1756. create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK); 1757. /* for(i = 0; i<r->ntoilet; i++) 1758. create_feature(r->toilets[i]->x, r->toilets[i]->y, aroom, TOILET);*/ 1759. for(i = 0; i<r->npool; i++) 1760. create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL); 1761. for(i = 0; i<r->nfountain; i++) 1762. create_feature(r->fountains[i]->x, r->fountains[i]->y, 1763. aroom, FOUNTAIN); 1764. for(i = 0; i<r->naltar; i++) 1765. create_altar(r->altars[i], aroom); 1766. for(i = 0; i<r->ndoor; i++) 1767. create_door(r->doors[i], aroom); 1768. 1769. /* The traps */ 1770. for(i = 0; i<r->ntrap; i++) 1771. create_trap(r->traps[i], aroom); 1772. 1773. /* The monsters */ 1774. for(i = 0; i<r->nmonster; i++) 1775. create_monster(r->monsters[i], aroom); 1776. 1777. /* The objects */ 1778. for(i = 0; i<r->nobject; i++) 1779. create_object(r->objects[i], aroom); 1780. 1781. /* The gold piles */ 1782. for(i = 0; i<r->ngold; 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<nrooms;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<nrooms; i++) 2130. if (tmproom[i]->parent) { 2131. /* Search the parent room */ 2132. for(j=0; j<nrooms; 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<ncorr; 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*/