Source:NetHack 3.2.0/mkroom.c
Revision as of 08:57, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.2.0/mkroom.c moved to Source:NetHack 3.2.0/mkroom.c: Robot: moved page)
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
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: @(#)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 ; i<croom->nsubrooms;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; i<r->nsubrooms; 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<nroom; 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; i<r->nsubrooms; 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<nroom; 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*/