abstract
| - Below is the full text to mkroom.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/mkroom.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)mkroom.c 3.2 93/04/04 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. /* 6. * Entry points: 7. * mkroom() -- make and stock a room of a given type 8. * nexttodoor() -- return TRUE if adjacent to a door 9. * has_dnstairs() -- return TRUE if given room has a down staircase 10. * has_upstairs() -- return TRUE if given room has an up staircase 11. * courtmon() -- generate a court monster 12. * save_rooms() -- save rooms into file fd 13. * rest_rooms() -- restore rooms from file fd 14. */ 15. 16. #include "hack.h" 17. 18. #ifdef OVLB 19. static boolean FDECL(isbig, (struct mkroom *)); 20. static struct mkroom * FDECL(pick_room,(BOOLEAN_P)); 21. static void NDECL(mkshop), FDECL(mkzoo,(int)), NDECL(mkswamp); 22. static void NDECL(mktemple); 23. static coord * FDECL(shrine_pos, (int)); 24. static struct permonst * NDECL(morguemon); 25. static struct permonst * NDECL(squadmon); 26. static void FDECL(save_room, (int,struct mkroom *)); 27. static void FDECL(rest_room, (int,struct mkroom *)); 28. #endif /* OVLB */ 29. 30. #define sq(x) ((x)*(x)) 31. 32. extern const struct shclass shtypes[]; /* defined in shknam.c */ 33. 34. #ifdef OVLB 35. 36. static boolean 37. isbig(sroom) 38. register struct mkroom *sroom; 39. { 40. register int area = (sroom->hx - sroom->lx + 1) 41. * (sroom->hy - sroom->ly + 1); 42. return((boolean)( area > 20 )); 43. } 44. 45. void 46. mkroom(roomtype) 47. /* make and stock a room of a given type */ 48. int roomtype; 49. { 50. if (roomtype >= SHOPBASE) 51. mkshop(); /* someday, we should be able to specify shop type */ 52. else switch(roomtype) { 53. case COURT: mkzoo(COURT); break; 54. case ZOO: mkzoo(ZOO); break; 55. case BEEHIVE: mkzoo(BEEHIVE); break; 56. case MORGUE: mkzoo(MORGUE); break; 57. case BARRACKS: mkzoo(BARRACKS); break; 58. case SWAMP: mkswamp(); break; 59. case TEMPLE: mktemple(); break; 60. default: impossible("Tried to make a room of type %d.", roomtype); 61. } 62. } 63. 64. static void 65. mkshop() 66. { 67. register struct mkroom *sroom; 68. int i = -1; 69. #ifdef WIZARD 70. # ifdef GCC_WARN 71. register char *ep = (char *)0; 72. # else 73. register char *ep; 74. # endif 75. 76. /* first determine shoptype */ 77. if(wizard){ 78. ep = getenv("SHOPTYPE"); 79. if(ep){ 80. if(*ep == 'z' || *ep == 'Z'){ 81. mkzoo(ZOO); 82. return; 83. } 84. if(*ep == 'm' || *ep == 'M'){ 85. mkzoo(MORGUE); 86. return; 87. } 88. if(*ep == 'b' || *ep == 'B'){ 89. mkzoo(BEEHIVE); 90. return; 91. } 92. if(*ep == 't' || *ep == 'T' || *ep == '\\'){ 93. mkzoo(COURT); 94. return; 95. } 96. if(*ep == 's' || *ep == 'S'){ 97. mkzoo(BARRACKS); 98. return; 99. } 100. if(*ep == '_'){ 101. mktemple(); 102. return; 103. } 104. if(*ep == '}'){ 105. mkswamp(); 106. return; 107. } 108. for(i=0; shtypes[i].name; i++) 109. if(*ep == def_oc_syms[(int)shtypes[i].symb]) 110. goto gottype; 111. if(*ep == 'g' || *ep == 'G') 112. i = 0; 113. else 114. i = -1; 115. } 116. } 117. gottype: 118. #endif 119. for(sroom = &rooms[0]; ; sroom++){ 120. if(sroom->hx < 0) return; 121. if(sroom - rooms >= nroom) { 122. pline("rooms not closed by -1?"); 123. return; 124. } 125. if(sroom->rtype != OROOM) continue; 126. if(has_dnstairs(sroom) || has_upstairs(sroom)) 127. continue; 128. if( 129. #ifdef WIZARD 130. (wizard && ep && sroom->doorct != 0) || 131. #endif 132. sroom->doorct == 1) break; 133. } 134. if (!sroom->rlit) { 135. int x, y; 136. 137. for(x = sroom->lx - 1; x <= sroom->hx + 1; x++) 138. for(y = sroom->ly - 1; y <= sroom->hy + 1; y++) 139. levl[x][y].lit = 1; 140. sroom->rlit = 1; 141. } 142. 143. if(i < 0) { /* shoptype not yet determined */ 144. register int j; 145. 146. /* pick a shop type at random */ 147. for (j = rnd(100), i = 0; (j -= shtypes[i].prob) > 0; i++) 148. continue; 149. 150. /* big rooms cannot be wand or book shops, 151. * - so make them general stores 152. */ 153. if(isbig(sroom) && (shtypes[i].symb == WAND_CLASS 154. || shtypes[i].symb == SPBOOK_CLASS)) i = 0; 155. } 156. sroom->rtype = SHOPBASE + i; 157. 158. /* set room bits before stocking the shop */ 159. #ifdef SPECIALIZATION 160. topologize(sroom, FALSE); /* doesn't matter - this is a special room */ 161. #else 162. topologize(sroom); 163. #endif 164. 165. /* stock the room with a shopkeeper and artifacts */ 166. stock_room(i, sroom); 167. } 168. 169. static struct mkroom * 170. pick_room(strict) 171. register boolean strict; 172. /* pick an unused room, preferably with only one door */ 173. { 174. register struct mkroom *sroom; 175. register int i = nroom; 176. 177. for(sroom = &rooms[rn2(nroom)]; i--; sroom++) { 178. if(sroom == &rooms[nroom]) 179. sroom = &rooms[0]; 180. if(sroom->hx < 0) 181. return (struct mkroom *)0; 182. if(sroom->rtype != OROOM) continue; 183. if(!strict) { 184. if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3))) 185. continue; 186. } else if(has_upstairs(sroom) || has_dnstairs(sroom)) 187. continue; 188. if(sroom->doorct == 1 || !rn2(5) 189. #ifdef WIZARD 190. || wizard 191. #endif 192. ) 193. return sroom; 194. } 195. return (struct mkroom *)0; 196. } 197. 198. static void 199. mkzoo(type) 200. int type; 201. { 202. register struct mkroom *sroom; 203. 204. if ((sroom = pick_room(FALSE)) != 0) { 205. sroom->rtype = type; 206. fill_zoo(sroom); 207. } 208. } 209. 210. void 211. fill_zoo(sroom) 212. struct mkroom *sroom; 213. { 214. struct monst *mon; 215. register int sx,sy,i; 216. int sh, tx, ty, goldlim, type = sroom->rtype; 217. int rmno = (sroom - rooms) + ROOMOFFSET; 218. coord mm; 219. 220. #ifdef GCC_WARN 221. tx = ty = goldlim = 0; 222. #endif 223. 224. sh = sroom->fdoor; 225. switch(type) { 226. case COURT: 227. if(level.flags.is_maze_lev) { 228. for(tx = sroom->lx; tx <= sroom->hx; tx++) 229. for(ty = sroom->ly; ty <= sroom->hy; ty++) 230. if(IS_THRONE(levl[tx][ty].typ)) 231. goto throne_placed; 232. } 233. i = 100; 234. do { /* don't place throne on top of stairs */ 235. (void) somexy(sroom, &mm); 236. tx = mm.x; ty = mm.y; 237. } while (occupied((xchar)tx, (xchar)ty) && --i > 0); 238. throne_placed: 239. /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ 240. break; 241. case BEEHIVE: 242. tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2; 243. ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2; 244. if(sroom->irregular) { 245. /* center might not be valid, so put queen elsewhere */ 246. if(levl[tx][ty].roomno != rmno || levl[tx][ty].edge) { 247. (void) somexy(sroom, &mm); 248. tx = mm.x; ty = mm.y; 249. } 250. } 251. break; 252. case ZOO: 253. goldlim = 500 * level_difficulty(); 254. break; 255. } 256. for(sx = sroom->lx; sx <= sroom->hx; sx++) 257. for(sy = sroom->ly; sy <= sroom->hy; sy++) { 258. if(sroom->irregular) { 259. if(levl[sx][sy].roomno != rmno || 260. levl[sx][sy].edge || 261. (sroom->doorct && 262. distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)) 263. continue; 264. } else if(!SPACE_POS(levl[sx][sy].typ) || 265. (sroom->doorct && 266. ((sx == sroom->lx && doors[sh].x == sx-1) || 267. (sx == sroom->hx && doors[sh].x == sx+1) || 268. (sy == sroom->ly && doors[sh].y == sy-1) || 269. (sy == sroom->hy && doors[sh].y == sy+1)))) 270. continue; 271. /* don't place monster on explicitly placed throne */ 272. if(type == COURT && IS_THRONE(levl[sx][sy].typ)) 273. continue; 274. mon = makemon( 275. (type == COURT) ? courtmon() : 276. (type == BARRACKS) ? squadmon() : 277. (type == MORGUE) ? morguemon() : 278. (type == BEEHIVE) ? 279. (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : 280. &mons[PM_KILLER_BEE]) : 281. (struct permonst *) 0, 282. sx, sy); 283. if(mon) { 284. mon->msleep = 1; 285. if (type==COURT && mon->mpeaceful) { 286. mon->mpeaceful = 0; 287. set_malign(mon); 288. } 289. } 290. switch(type) { 291. case ZOO: 292. if(sroom->doorct) 293. { 294. int distval = dist2(sx,sy,doors[sh].x,doors[sh].y); 295. i = sq(distval); 296. } 297. else 298. i = goldlim; 299. if(i >= goldlim) i = 5*level_difficulty(); 300. goldlim -= i; 301. mkgold((long) rn1(i, 10), sx, sy); 302. break; 303. case MORGUE: 304. if(!rn2(5)) 305. (void) mk_tt_object(CORPSE, sx, sy); 306. if(!rn2(10)) /* lots of treasure buried with dead */ 307. (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, 308. sx, sy, TRUE); 309. break; 310. case BEEHIVE: 311. if(!rn2(3)) 312. (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, TRUE); 313. break; 314. case BARRACKS: 315. if(!rn2(20)) /* the payroll and some loot */ 316. (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, 317. sx, sy, TRUE); 318. break; 319. } 320. } 321. switch (type) { 322. case COURT: 323. { 324. struct obj *chest; 325. levl[tx][ty].typ = THRONE; 326. (void) somexy(sroom, &mm); 327. mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y); 328. chest = mksobj_at(CHEST, mm.x, mm.y, TRUE); /* the royal coffers */ 329. chest->spe = 2; /* so it can be found later */ 330. level.flags.has_court = 1; 331. break; 332. } 333. case BARRACKS: 334. level.flags.has_barracks = 1; 335. break; 336. case ZOO: 337. level.flags.has_zoo = 1; 338. break; 339. case MORGUE: 340. level.flags.has_morgue = 1; 341. break; 342. case SWAMP: 343. level.flags.has_swamp = 1; 344. break; 345. case BEEHIVE: 346. level.flags.has_beehive = 1; 347. break; 348. } 349. } 350. 351. void 352. mkundead(mm) /* make a swarm of undead around mm */ 353. coord *mm; 354. { 355. register int cnt = (level_difficulty() + 1)/10 + rnd(5); 356. register struct permonst *mdat; 357. 358. while(cnt--) { 359. mdat = morguemon(); 360. if(enexto(mm, mm->x, mm->y, mdat)) 361. (void) makemon(mdat, mm->x, mm->y); 362. } 363. level.flags.graveyard = TRUE; /* reduced chance for undead corpse */ 364. } 365. 366. static struct permonst * 367. morguemon() 368. { 369. register int i = rn2(100), hd = rn2(level_difficulty()); 370. 371. if(hd > 10 && i < 10) 372. return((Inhell || In_endgame(&u.uz)) ? mkclass(S_DEMON,0) : 373. &mons[ndemon(A_NONE)]); 374. if(hd > 8 && i > 85) 375. return(mkclass(S_VAMPIRE,0)); 376. 377. return((i < 20) ? &mons[PM_GHOST] 378. : (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE,0)); 379. } 380. 381. static void 382. mkswamp() /* Michiel Huisjes & Fred de Wilde */ 383. { 384. register struct mkroom *sroom; 385. register int sx,sy,i,eelct = 0; 386. 387. for(i=0; i<5; i++) { /* turn up to 5 rooms swampy */ 388. sroom = &rooms[rn2(nroom)]; 389. if(sroom->hx < 0 || sroom->rtype != OROOM || 390. has_upstairs(sroom) || has_dnstairs(sroom)) 391. continue; 392. 393. /* satisfied; make a swamp */ 394. sroom->rtype = SWAMP; 395. for(sx = sroom->lx; sx <= sroom->hx; sx++) 396. for(sy = sroom->ly; sy <= sroom->hy; sy++) 397. if(!OBJ_AT(sx, sy) && 398. !MON_AT(sx, sy) && !t_at(sx,sy) && !nexttodoor(sx,sy)) { 399. if((sx+sy)%2) { 400. levl[sx][sy].typ = POOL; 401. if(!eelct || !rn2(4)) { 402. /* mkclass() won't do, as we might get kraken */ 403. (void) makemon(rn2(5) ? &mons[PM_GIANT_EEL] 404. : &mons[PM_ELECTRIC_EEL], 405. sx, sy); 406. eelct++; 407. } 408. } else 409. if(!rn2(4)) /* swamps tend to be moldy */ 410. (void) makemon(mkclass(S_FUNGUS,0), sx, sy); 411. } 412. level.flags.has_swamp = 1; 413. } 414. } 415. 416. static coord * 417. shrine_pos(roomno) 418. int roomno; 419. { 420. static coord buf; 421. struct mkroom *troom = &rooms[roomno - ROOMOFFSET]; 422. 423. buf.x = troom->lx + ((troom->hx - troom->lx) / 2); 424. buf.y = troom->ly + ((troom->hy - troom->ly) / 2); 425. return(&buf); 426. } 427. 428. static void 429. mktemple() 430. { 431. register struct mkroom *sroom; 432. coord *shrine_spot; 433. register struct rm *lev; 434. 435. if(!(sroom = pick_room(TRUE))) return; 436. 437. /* set up Priest and shrine */ 438. sroom->rtype = TEMPLE; 439. /* 440. * In temples, shrines are blessed altars 441. * located in the center of the room 442. */ 443. shrine_spot = shrine_pos((sroom - rooms) + ROOMOFFSET); 444. lev = &levl[shrine_spot->x][shrine_spot->y]; 445. lev->typ = ALTAR; 446. lev->altarmask = induced_align(80); 447. priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE); 448. lev->altarmask |= AM_SHRINE; 449. level.flags.has_temple = 1; 450. } 451. 452. boolean 453. nexttodoor(sx,sy) 454. register int sx, sy; 455. { 456. register int dx, dy; 457. register struct rm *lev; 458. for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) { 459. if(!isok(sx+dx, sy+dy)) continue; 460. if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) || 461. lev->typ == SDOOR) 462. return(TRUE); 463. } 464. return(FALSE); 465. } 466. 467. boolean 468. has_dnstairs(sroom) 469. register struct mkroom *sroom; 470. { 471. if (sroom == dnstairs_room) 472. return TRUE; 473. if (sstairs.sx && !sstairs.up) 474. return((boolean)(sroom == sstairs_room)); 475. return FALSE; 476. } 477. 478. boolean 479. has_upstairs(sroom) 480. register struct mkroom *sroom; 481. { 482. if (sroom == upstairs_room) 483. return TRUE; 484. if (sstairs.sx && sstairs.up) 485. return((boolean)(sroom == sstairs_room)); 486. return FALSE; 487. } 488. 489. #endif /* OVLB */ 490. #ifdef OVL0 491. 492. int 493. somex(croom) 494. register struct mkroom *croom; 495. { 496. return rn2(croom->hx-croom->lx+1) + croom->lx; 497. } 498. 499. int 500. somey(croom) 501. register struct mkroom *croom; 502. { 503. return rn2(croom->hy-croom->ly+1) + croom->ly; 504. } 505. 506. boolean 507. inside_room(croom, x, y) 508. struct mkroom *croom; 509. xchar x, y; 510. { 511. return((boolean)(x >= croom->lx-1 && x <= croom->hx+1 && 512. y >= croom->ly-1 && y <= croom->hy+1)); 513. } 514. 515. boolean 516. somexy(croom, c) 517. struct mkroom *croom; 518. coord *c; 519. { 520. int try_cnt = 0; 521. int i; 522. 523. if (croom->irregular) { 524. i = (croom - rooms) + ROOMOFFSET; 525. 526. while(try_cnt++ < 100) { 527. c->x = somex(croom); 528. c->y = somey(croom); 529. if(!levl[c->x][c->y].edge && levl[c->x][c->y].roomno == i) 530. return TRUE; 531. } 532. /* try harder; exhaustively search until one is found */ 533. for(c->x = croom->lx; c->x <= croom->hx; c->x++) 534. for(c->y = croom->ly; c->y <= croom->hy; c->y++) 535. if(!levl[c->x][c->y].edge && levl[c->x][c->y].roomno == i) 536. return TRUE; 537. return FALSE; 538. } 539. 540. if (!croom->nsubrooms) { 541. c->x = somex(croom); 542. c->y = somey(croom); 543. return TRUE; 544. } 545. 546. /* Check that coords doesn't fall into a subroom or into a wall */ 547. 548. while(try_cnt++ < 100) { 549. c->x = somex(croom); 550. c->y = somey(croom); 551. if (IS_WALL(levl[c->x][c->y].typ)) 552. continue; 553. for(i=0 ; insubrooms;i++) 554. if(inside_room(croom->sbrooms[i], c->x, c->y)) 555. goto you_lose; 556. break; 557. you_lose: ; 558. } 559. if (try_cnt >= 100) 560. return FALSE; 561. return TRUE; 562. } 563. 564. /* 565. * Search for a special room given its type (zoo, court, etc...) 566. * Special values : 567. * - ANY_SHOP 568. * - ANY_TYPE 569. */ 570. 571. struct mkroom * 572. search_special(type) 573. schar type; 574. { 575. register struct mkroom *croom; 576. 577. for(croom = &rooms[0]; croom->hx >= 0; croom++) 578. if((type == ANY_TYPE && croom->rtype != OROOM) || 579. (type == ANY_SHOP && croom->rtype >= SHOPBASE) || 580. croom->rtype == type) 581. return croom; 582. for(croom = &subrooms[0]; croom->hx >= 0; croom++) 583. if((type == ANY_TYPE && croom->rtype != OROOM) || 584. (type == ANY_SHOP && croom->rtype >= SHOPBASE) || 585. croom->rtype == type) 586. return croom; 587. return (struct mkroom *) 0; 588. } 589. 590. #endif /* OVL0 */ 591. #ifdef OVLB 592. 593. struct permonst * 594. courtmon() 595. { 596. int i = rn2(60) + rn2(3*level_difficulty()); 597. if (i > 100) return(mkclass(S_DRAGON,0)); 598. else if (i > 95) return(mkclass(S_GIANT,0)); 599. else if (i > 85) return(mkclass(S_TROLL,0)); 600. else if (i > 75) return(mkclass(S_CENTAUR,0)); 601. else if (i > 60) return(mkclass(S_ORC,0)); 602. else if (i > 45) return(&mons[PM_BUGBEAR]); 603. else if (i > 30) return(&mons[PM_HOBGOBLIN]); 604. else if (i > 15) return(mkclass(S_GNOME,0)); 605. else return(mkclass(S_KOBOLD,0)); 606. } 607. 608. #define NSTYPES (PM_CAPTAIN - PM_SOLDIER + 1) 609. 610. static struct { 611. unsigned pm; 612. unsigned prob; 613. } squadprob[NSTYPES] = { 614. {PM_SOLDIER, 80}, {PM_SERGEANT, 15}, {PM_LIEUTENANT, 4}, {PM_CAPTAIN, 1} 615. }; 616. 617. static struct permonst * 618. squadmon() /* return soldier types. */ 619. { 620. int sel_prob, i, cpro, mndx; 621. 622. sel_prob = rnd(80+level_difficulty()); 623. 624. cpro = 0; 625. for (i = 0; i < NSTYPES; i++) { 626. cpro += squadprob[i].prob; 627. if (cpro > sel_prob) { 628. mndx = squadprob[i].pm; 629. goto gotone; 630. } 631. } 632. mndx = squadprob[rn2(NSTYPES)].pm; 633. gotone: 634. if (!(mvitals[mndx].mvflags & G_GONE)) return(&mons[mndx]); 635. else return((struct permonst *) 0); 636. } 637. 638. /* 639. * save_room : A recursive function that saves a room and its subrooms 640. * (if any). 641. */ 642. 643. static void 644. save_room(fd, r) 645. int fd; 646. struct mkroom *r; 647. { 648. short i; 649. /* 650. * Well, I really should write only useful informations instead 651. * of writing the whole structure. That is I should not write 652. * the subrooms pointers, but who cares ? 653. */ 654. bwrite(fd, (genericptr_t) r, sizeof(struct mkroom)); 655. for(i=0; insubrooms; i++) 656. save_room(fd, r->sbrooms[i]); 657. } 658. 659. /* 660. * save_rooms : Save all the rooms on disk! 661. */ 662. 663. void 664. save_rooms(fd) 665. int fd; 666. { 667. short i; 668. 669. /* First, write the number of rooms */ 670. bwrite(fd, (genericptr_t) &nroom, sizeof(nroom)); 671. for(i=0; i 672. save_room(fd, &rooms[i]); 673. } 674. 675. static void 676. rest_room(fd, r) 677. int fd; 678. struct mkroom *r; 679. { 680. short i; 681. 682. mread(fd, (genericptr_t) r, sizeof(struct mkroom)); 683. for(i=0; insubrooms; i++) { 684. r->sbrooms[i] = &subrooms[nsubroom]; 685. rest_room(fd, &subrooms[nsubroom++]); 686. } 687. } 688. 689. /* 690. * rest_rooms : That's for restore rooms. Read the rooms structure from 691. * the disk. 692. */ 693. 694. void 695. rest_rooms(fd) 696. int fd; 697. { 698. short i; 699. 700. mread(fd, (genericptr_t) &nroom, sizeof(nroom)); 701. nsubroom = 0; 702. for(i = 0; i 703. rest_room(fd, &rooms[i]); 704. rooms[i].resident = (struct monst *)0; 705. } 706. rooms[nroom].hx = -1; /* restore ending flags */ 707. subrooms[nsubroom].hx = -1; 708. } 709. #endif /* OVLB */ 710. 711. /*mkroom.c*/
|