Source:NetHack 3.4.3/src/region.c
Revision as of 15:00, 4 March 2008 by Kernigh bot (talk | contribs) (Region.c moved to Source:Region.c: Robot: moved page)
Below is the full text to src/region.c from NetHack 3.4.3. To link to a particular line, write [[region.c#line123]], for example.
Contents
- 1 Top of file
- 2 inside_rect
- 3 inside_region
- 4 create_region
- 5 add_rect_to_reg
- 6 add_mon_to_reg
- 7 remove_mon_from_reg
- 8 mon_in_region
- 9 clone_region
- 10 free_region
- 11 add_region
- 12 remove_region
- 13 clear_regions
- 14 run_regions
- 15 in_out_region
- 16 m_in_out_region
- 17 update_player_regions
- 18 update_monster_region
- 19 replace_mon_regions
- 20 remove_mon_from_regions
- 21 visible_region_at
- 22 show_region
- 23 save_regions
- 24 rest_regions
- 25 reset_region_mids
- 26 create_msg_region
- 27 enter_force_field
- 28 create_force_field
- 29 expire_gas_cloud
- 30 inside_gas_cloud
- 31 create_gas_cloud
Top of file
1. /* SCCS Id: @(#)region.c 3.4 2002/10/15 */ 2. /* Copyright (c) 1996 by Jean-Christophe Collet */ 3. /* NetHack may be freely redistributed. See license for details. */ 4.
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.
5. #include "hack.h" 6. #include "lev.h" 7. 8. /* 9. * This should really go into the level structure, but 10. * I'll start here for ease. It *WILL* move into the level 11. * structure eventually. 12. */ 13. 14. static NhRegion **regions; 15. static int n_regions = 0; 16. static int max_regions = 0; 17. 18. #define NO_CALLBACK (-1) 19. 20. boolean FDECL(inside_gas_cloud, (genericptr,genericptr)); 21. boolean FDECL(expire_gas_cloud, (genericptr,genericptr)); 22. boolean FDECL(inside_rect, (NhRect *,int,int)); 23. boolean FDECL(inside_region, (NhRegion *,int,int)); 24. NhRegion *FDECL(create_region, (NhRect *,int)); 25. void FDECL(add_rect_to_reg, (NhRegion *,NhRect *)); 26. void FDECL(add_mon_to_reg, (NhRegion *,struct monst *)); 27. void FDECL(remove_mon_from_reg, (NhRegion *,struct monst *)); 28. boolean FDECL(mon_in_region, (NhRegion *,struct monst *)); 29. 30. #if 0 31. NhRegion *FDECL(clone_region, (NhRegion *)); 32. #endif 33. void FDECL(free_region, (NhRegion *)); 34. void FDECL(add_region, (NhRegion *)); 35. void FDECL(remove_region, (NhRegion *)); 36. 37. #if 0 38. void FDECL(replace_mon_regions, (struct monst *,struct monst *)); 39. void FDECL(remove_mon_from_regions, (struct monst *)); 40. NhRegion *FDECL(create_msg_region, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P, 41. const char *,const char *)); 42. boolean FDECL(enter_force_field, (genericptr,genericptr)); 43. NhRegion *FDECL(create_force_field, (XCHAR_P,XCHAR_P,int,int)); 44. #endif 45. 46. static void FDECL(reset_region_mids, (NhRegion *)); 47. 48. static callback_proc callbacks[] = { 49. #define INSIDE_GAS_CLOUD 0 50. inside_gas_cloud, 51. #define EXPIRE_GAS_CLOUD 1 52. expire_gas_cloud 53. }; 54.
inside_rect
55. /* Should be inlined. */ 56. boolean 57. inside_rect(r, x, y) 58. NhRect *r; 59. int x, y; 60. { 61. return (x >= r->lx && x <= r->hx && y >= r->ly && y <= r->hy); 62. } 63.
inside_region
64. /* 65. * Check if a point is inside a region. 66. */ 67. boolean 68. inside_region(reg, x, y) 69. NhRegion *reg; 70. int x, y; 71. { 72. int i; 73. 74. if (reg == NULL || !inside_rect(&(reg->bounding_box), x, y)) 75. return FALSE; 76. for (i = 0; i < reg->nrects; i++) 77. if (inside_rect(&(reg->rects[i]), x, y)) 78. return TRUE; 79. return FALSE; 80. } 81.
create_region
82. /* 83. * Create a region. It does not activate it. 84. */ 85. NhRegion * 86. create_region(rects, nrect) 87. NhRect *rects; 88. int nrect; 89. { 90. int i; 91. NhRegion *reg; 92. 93. reg = (NhRegion *) alloc(sizeof (NhRegion)); 94. /* Determines bounding box */ 95. if (nrect > 0) { 96. reg->bounding_box = rects[0]; 97. } else { 98. reg->bounding_box.lx = 99; 99. reg->bounding_box.ly = 99; 100. reg->bounding_box.hx = 0; 101. reg->bounding_box.hy = 0; 102. } 103. reg->nrects = nrect; 104. reg->rects = nrect > 0 ? (NhRect *)alloc((sizeof (NhRect)) * nrect) : NULL; 105. for (i = 0; i < nrect; i++) { 106. if (rects[i].lx < reg->bounding_box.lx) 107. reg->bounding_box.lx = rects[i].lx; 108. if (rects[i].ly < reg->bounding_box.ly) 109. reg->bounding_box.ly = rects[i].ly; 110. if (rects[i].hx > reg->bounding_box.hx) 111. reg->bounding_box.hx = rects[i].hx; 112. if (rects[i].hy > reg->bounding_box.hy) 113. reg->bounding_box.hy = rects[i].hy; 114. reg->rects[i] = rects[i]; 115. } 116. reg->ttl = -1; /* Defaults */ 117. reg->attach_2_u = FALSE; 118. reg->attach_2_m = 0; 119. /* reg->attach_2_o = NULL; */ 120. reg->enter_msg = NULL; 121. reg->leave_msg = NULL; 122. reg->expire_f = NO_CALLBACK; 123. reg->enter_f = NO_CALLBACK; 124. reg->can_enter_f = NO_CALLBACK; 125. reg->leave_f = NO_CALLBACK; 126. reg->can_leave_f = NO_CALLBACK; 127. reg->inside_f = NO_CALLBACK; 128. clear_hero_inside(reg); 129. clear_heros_fault(reg); 130. reg->n_monst = 0; 131. reg->max_monst = 0; 132. reg->monsters = NULL; 133. reg->arg = NULL; 134. return reg; 135. } 136.
add_rect_to_reg
137. /* 138. * Add rectangle to region. 139. */ 140. void 141. add_rect_to_reg(reg, rect) 142. NhRegion *reg; 143. NhRect *rect; 144. { 145. NhRect *tmp_rect; 146. 147. tmp_rect = (NhRect *) alloc(sizeof (NhRect) * (reg->nrects + 1)); 148. if (reg->nrects > 0) { 149. (void) memcpy((genericptr_t) tmp_rect, (genericptr_t) reg->rects, 150. (sizeof (NhRect) * reg->nrects)); 151. free((genericptr_t) reg->rects); 152. } 153. tmp_rect[reg->nrects] = *rect; 154. reg->nrects++; 155. reg->rects = tmp_rect; 156. /* Update bounding box if needed */ 157. if (reg->bounding_box.lx > rect->lx) 158. reg->bounding_box.lx = rect->lx; 159. if (reg->bounding_box.ly > rect->ly) 160. reg->bounding_box.ly = rect->ly; 161. if (reg->bounding_box.hx < rect->hx) 162. reg->bounding_box.hx = rect->hx; 163. if (reg->bounding_box.hy < rect->hy) 164. reg->bounding_box.hy = rect->hy; 165. } 166.
add_mon_to_reg
167. /* 168. * Add a monster to the region 169. */ 170. void 171. add_mon_to_reg(reg, mon) 172. NhRegion *reg; 173. struct monst *mon; 174. { 175. int i; 176. unsigned *tmp_m; 177. 178. if (reg->max_monst <= reg->n_monst) { 179. tmp_m = (unsigned *) 180. alloc(sizeof (unsigned) * (reg->max_monst + MONST_INC)); 181. if (reg->max_monst > 0) { 182. for (i = 0; i < reg->max_monst; i++) 183. tmp_m[i] = reg->monsters[i]; 184. free((genericptr_t) reg->monsters); 185. } 186. reg->monsters = tmp_m; 187. reg->max_monst += MONST_INC; 188. } 189. reg->monsters[reg->n_monst++] = mon->m_id; 190. } 191.
remove_mon_from_reg
192. /* 193. * Remove a monster from the region list (it left or died...) 194. */ 195. void 196. remove_mon_from_reg(reg, mon) 197. NhRegion *reg; 198. struct monst *mon; 199. { 200. register int i; 201. 202. for (i = 0; i < reg->n_monst; i++) 203. if (reg->monsters[i] == mon->m_id) { 204. reg->n_monst--; 205. reg->monsters[i] = reg->monsters[reg->n_monst]; 206. return; 207. } 208. } 209.
mon_in_region
210. /* 211. * Check if a monster is inside the region. 212. * It's probably quicker to check with the region internal list 213. * than to check for coordinates. 214. */ 215. boolean 216. mon_in_region(reg, mon) 217. NhRegion *reg; 218. struct monst *mon; 219. { 220. int i; 221. 222. for (i = 0; i < reg->n_monst; i++) 223. if (reg->monsters[i] == mon->m_id) 224. return TRUE; 225. return FALSE; 226. } 227. 228. #if 0 229. /* not yet used */ 230.
clone_region
231. /* 232. * Clone (make a standalone copy) the region. 233. */ 234. NhRegion * 235. clone_region(reg) 236. NhRegion *reg; 237. { 238. NhRegion *ret_reg; 239. 240. ret_reg = create_region(reg->rects, reg->nrects); 241. ret_reg->ttl = reg->ttl; 242. ret_reg->attach_2_u = reg->attach_2_u; 243. ret_reg->attach_2_m = reg->attach_2_m; 244. /* ret_reg->attach_2_o = reg->attach_2_o; */ 245. ret_reg->expire_f = reg->expire_f; 246. ret_reg->enter_f = reg->enter_f; 247. ret_reg->can_enter_f = reg->can_enter_f; 248. ret_reg->leave_f = reg->leave_f; 249. ret_reg->can_leave_f = reg->can_leave_f; 250. ret_reg->player_flags = reg->player_flags; /* set/clear_hero_inside,&c*/ 251. ret_reg->n_monst = reg->n_monst; 252. if (reg->n_monst > 0) { 253. ret_reg->monsters = (unsigned *) 254. alloc((sizeof (unsigned)) * reg->n_monst); 255. (void) memcpy((genericptr_t) ret_reg->monsters, (genericptr_t) reg->monsters, 256. sizeof (unsigned) * reg->n_monst); 257. } else 258. ret_reg->monsters = NULL; 259. return ret_reg; 260. } 261. 262. #endif /*0*/ 263.
free_region
264. /* 265. * Free mem from region. 266. */ 267. void 268. free_region(reg) 269. NhRegion *reg; 270. { 271. if (reg) { 272. if (reg->rects) 273. free((genericptr_t) reg->rects); 274. if (reg->monsters) 275. free((genericptr_t) reg->monsters); 276. free((genericptr_t) reg); 277. } 278. } 279.
add_region
280. /* 281. * Add a region to the list. 282. * This actually activates the region. 283. */ 284. void 285. add_region(reg) 286. NhRegion *reg; 287. { 288. NhRegion **tmp_reg; 289. int i, j; 290. 291. if (max_regions <= n_regions) { 292. tmp_reg = regions; 293. regions = (NhRegion **)alloc(sizeof (NhRegion *) * (max_regions + 10)); 294. if (max_regions > 0) { 295. (void) memcpy((genericptr_t) regions, (genericptr_t) tmp_reg, 296. max_regions * sizeof (NhRegion *)); 297. free((genericptr_t) tmp_reg); 298. } 299. max_regions += 10; 300. } 301. regions[n_regions] = reg; 302. n_regions++; 303. /* Check for monsters inside the region */ 304. for (i = reg->bounding_box.lx; i <= reg->bounding_box.hx; i++) 305. for (j = reg->bounding_box.ly; j <= reg->bounding_box.hy; j++) { 306. /* Some regions can cross the level boundaries */ 307. if (!isok(i,j)) 308. continue; 309. if (MON_AT(i, j) && inside_region(reg, i, j)) 310. add_mon_to_reg(reg, level.monsters[i][j]); 311. if (reg->visible && cansee(i, j)) 312. newsym(i, j); 313. } 314. /* Check for player now... */ 315. if (inside_region(reg, u.ux, u.uy)) 316. set_hero_inside(reg); 317. else 318. clear_hero_inside(reg); 319. } 320.
remove_region
321. /* 322. * Remove a region from the list & free it. 323. */ 324. void 325. remove_region(reg) 326. NhRegion *reg; 327. { 328. register int i, x, y; 329. 330. for (i = 0; i < n_regions; i++) 331. if (regions[i] == reg) 332. break; 333. if (i == n_regions) 334. return; 335. 336. /* Update screen if necessary */ 337. if (reg->visible) 338. for (x = reg->bounding_box.lx; x <= reg->bounding_box.hx; x++) 339. for (y = reg->bounding_box.ly; y <= reg->bounding_box.hy; y++) 340. if (isok(x,y) && inside_region(reg, x, y) && cansee(x, y)) 341. newsym(x, y); 342. 343. free_region(reg); 344. regions[i] = regions[n_regions - 1]; 345. regions[n_regions - 1] = (NhRegion *) 0; 346. n_regions--; 347. } 348.
clear_regions
349. /* 350. * Remove all regions and clear all related data (This must be down 351. * when changing level, for instance). 352. */ 353. void 354. clear_regions() 355. { 356. register int i; 357. 358. for (i = 0; i < n_regions; i++) 359. free_region(regions[i]); 360. n_regions = 0; 361. if (max_regions > 0) 362. free((genericptr_t) regions); 363. max_regions = 0; 364. regions = NULL; 365. } 366.
run_regions
367. /* 368. * This function is called every turn. 369. * It makes the regions age, if necessary and calls the appropriate 370. * callbacks when needed. 371. */ 372. void 373. run_regions() 374. { 375. register int i, j, k; 376. int f_indx; 377. 378. /* End of life ? */ 379. /* Do it backward because the array will be modified */ 380. for (i = n_regions - 1; i >= 0; i--) { 381. if (regions[i]->ttl == 0) { 382. if ((f_indx = regions[i]->expire_f) == NO_CALLBACK || 383. (*callbacks[f_indx])(regions[i], (genericptr_t) 0)) 384. remove_region(regions[i]); 385. } 386. } 387. 388. /* Process remaining regions */ 389. for (i = 0; i < n_regions; i++) { 390. /* Make the region age */ 391. if (regions[i]->ttl > 0) 392. regions[i]->ttl--; 393. /* Check if player is inside region */ 394. f_indx = regions[i]->inside_f; 395. if (f_indx != NO_CALLBACK && hero_inside(regions[i])) 396. (void) (*callbacks[f_indx])(regions[i], (genericptr_t) 0); 397. /* Check if any monster is inside region */ 398. if (f_indx != NO_CALLBACK) { 399. for (j = 0; j < regions[i]->n_monst; j++) { 400. struct monst *mtmp = find_mid(regions[i]->monsters[j], FM_FMON); 401. 402. if (!mtmp || mtmp->mhp <= 0 || 403. (*callbacks[f_indx])(regions[i], mtmp)) { 404. /* The monster died, remove it from list */ 405. k = (regions[i]->n_monst -= 1); 406. regions[i]->monsters[j] = regions[i]->monsters[k]; 407. regions[i]->monsters[k] = 0; 408. --j; /* current slot has been reused; recheck it next */ 409. } 410. } 411. } 412. } 413. } 414.
in_out_region
415. /* 416. * check whether player enters/leaves one or more regions. 417. */ 418. boolean 419. in_out_region(x, y) 420. xchar 421. x, y; 422. { 423. int i, f_indx; 424. 425. /* First check if we can do the move */ 426. for (i = 0; i < n_regions; i++) { 427. if (inside_region(regions[i], x, y) 428. && !hero_inside(regions[i]) && !regions[i]->attach_2_u) { 429. if ((f_indx = regions[i]->can_enter_f) != NO_CALLBACK) 430. if (!(*callbacks[f_indx])(regions[i], (genericptr_t) 0)) 431. return FALSE; 432. } else 433. if (hero_inside(regions[i]) 434. && !inside_region(regions[i], x, y) 435. && !regions[i]->attach_2_u) { 436. if ((f_indx = regions[i]->can_leave_f) != NO_CALLBACK) 437. if (!(*callbacks[f_indx])(regions[i], (genericptr_t) 0)) 438. return FALSE; 439. } 440. } 441. 442. /* Callbacks for the regions we do leave */ 443. for (i = 0; i < n_regions; i++) 444. if (hero_inside(regions[i]) && 445. !regions[i]->attach_2_u && !inside_region(regions[i], x, y)) { 446. clear_hero_inside(regions[i]); 447. if (regions[i]->leave_msg != NULL) 448. pline(regions[i]->leave_msg); 449. if ((f_indx = regions[i]->leave_f) != NO_CALLBACK) 450. (void) (*callbacks[f_indx])(regions[i], (genericptr_t) 0); 451. } 452. 453. /* Callbacks for the regions we do enter */ 454. for (i = 0; i < n_regions; i++) 455. if (!hero_inside(regions[i]) && 456. !regions[i]->attach_2_u && inside_region(regions[i], x, y)) { 457. set_hero_inside(regions[i]); 458. if (regions[i]->enter_msg != NULL) 459. pline(regions[i]->enter_msg); 460. if ((f_indx = regions[i]->enter_f) != NO_CALLBACK) 461. (void) (*callbacks[f_indx])(regions[i], (genericptr_t) 0); 462. } 463. return TRUE; 464. } 465.
m_in_out_region
466. /* 467. * check wether a monster enters/leaves one or more region. 468. */ 469. boolean 470. m_in_out_region(mon, x, y) 471. struct monst *mon; 472. xchar x, y; 473. { 474. int i, f_indx; 475. 476. /* First check if we can do the move */ 477. for (i = 0; i < n_regions; i++) { 478. if (inside_region(regions[i], x, y) && 479. !mon_in_region(regions[i], mon) && 480. regions[i]->attach_2_m != mon->m_id) { 481. if ((f_indx = regions[i]->can_enter_f) != NO_CALLBACK) 482. if (!(*callbacks[f_indx])(regions[i], mon)) 483. return FALSE; 484. } else if (mon_in_region(regions[i], mon) && 485. !inside_region(regions[i], x, y) && 486. regions[i]->attach_2_m != mon->m_id) { 487. if ((f_indx = regions[i]->can_leave_f) != NO_CALLBACK) 488. if (!(*callbacks[f_indx])(regions[i], mon)) 489. return FALSE; 490. } 491. } 492. 493. /* Callbacks for the regions we do leave */ 494. for (i = 0; i < n_regions; i++) 495. if (mon_in_region(regions[i], mon) && 496. regions[i]->attach_2_m != mon->m_id && 497. !inside_region(regions[i], x, y)) { 498. remove_mon_from_reg(regions[i], mon); 499. if ((f_indx = regions[i]->leave_f) != NO_CALLBACK) 500. (void) (*callbacks[f_indx])(regions[i], mon); 501. } 502. 503. /* Callbacks for the regions we do enter */ 504. for (i = 0; i < n_regions; i++) 505. if (!hero_inside(regions[i]) && 506. !regions[i]->attach_2_u && inside_region(regions[i], x, y)) { 507. add_mon_to_reg(regions[i], mon); 508. if ((f_indx = regions[i]->enter_f) != NO_CALLBACK) 509. (void) (*callbacks[f_indx])(regions[i], mon); 510. } 511. return TRUE; 512. } 513.
update_player_regions
514. /* 515. * Checks player's regions after a teleport for instance. 516. */ 517. void 518. update_player_regions() 519. { 520. register int i; 521. 522. for (i = 0; i < n_regions; i++) 523. if (!regions[i]->attach_2_u && inside_region(regions[i], u.ux, u.uy)) 524. set_hero_inside(regions[i]); 525. else 526. clear_hero_inside(regions[i]); 527. } 528.
update_monster_region
529. /* 530. * Ditto for a specified monster. 531. */ 532. void 533. update_monster_region(mon) 534. struct monst *mon; 535. { 536. register int i; 537. 538. for (i = 0; i < n_regions; i++) { 539. if (inside_region(regions[i], mon->mx, mon->my)) { 540. if (!mon_in_region(regions[i], mon)) 541. add_mon_to_reg(regions[i], mon); 542. } else { 543. if (mon_in_region(regions[i], mon)) 544. remove_mon_from_reg(regions[i], mon); 545. } 546. } 547. } 548. 549. #if 0
replace_mon_regions
550. /* not yet used */ 551. 552. /* 553. * Change monster pointer in regions 554. * This happens, for instance, when a monster grows and 555. * need a new structure (internally that is). 556. */ 557. void 558. replace_mon_regions(monold, monnew) 559. struct monst *monold, *monnew; 560. { 561. register int i; 562. 563. for (i = 0; i < n_regions; i++) 564. if (mon_in_region(regions[i], monold)) { 565. remove_mon_from_reg(regions[i], monold); 566. add_mon_to_reg(regions[i], monnew); 567. } 568. } 569.
remove_mon_from_regions
570. /* 571. * Remove monster from all regions it was in (ie monster just died) 572. */ 573. void 574. remove_mon_from_regions(mon) 575. struct monst *mon; 576. { 577. register int i; 578. 579. for (i = 0; i < n_regions; i++) 580. if (mon_in_region(regions[i], mon)) 581. remove_mon_from_reg(regions[i], mon); 582. } 583. 584. #endif /*0*/ 585.
visible_region_at
586. /* 587. * Check if a spot is under a visible region (eg: gas cloud). 588. * Returns NULL if not, otherwise returns region. 589. */ 590. NhRegion * 591. visible_region_at(x, y) 592. xchar x, y; 593. { 594. register int i; 595. 596. for (i = 0; i < n_regions; i++) 597. if (inside_region(regions[i], x, y) && regions[i]->visible && 598. regions[i]->ttl != 0) 599. return regions[i]; 600. return (NhRegion *) 0; 601. } 602.
show_region
603. void 604. show_region(reg, x, y) 605. NhRegion *reg; 606. xchar x, y; 607. { 608. show_glyph(x, y, reg->glyph); 609. } 610.
save_regions
611. /** 612. * save_regions : 613. */ 614. void 615. save_regions(fd, mode) 616. int fd; 617. int mode; 618. { 619. int i, j; 620. unsigned n; 621. 622. if (!perform_bwrite(mode)) goto skip_lots; 623. 624. bwrite(fd, (genericptr_t) &moves, sizeof (moves)); /* timestamp */ 625. bwrite(fd, (genericptr_t) &n_regions, sizeof (n_regions)); 626. for (i = 0; i < n_regions; i++) { 627. bwrite(fd, (genericptr_t) ®ions[i]->bounding_box, sizeof (NhRect)); 628. bwrite(fd, (genericptr_t) ®ions[i]->nrects, sizeof (short)); 629. for (j = 0; j < regions[i]->nrects; j++) 630. bwrite(fd, (genericptr_t) ®ions[i]->rects[j], sizeof (NhRect)); 631. bwrite(fd, (genericptr_t) ®ions[i]->attach_2_u, sizeof (boolean)); 632. n = 0; 633. bwrite(fd, (genericptr_t) ®ions[i]->attach_2_m, sizeof (unsigned)); 634. n = regions[i]->enter_msg != NULL ? strlen(regions[i]->enter_msg) : 0; 635. bwrite(fd, (genericptr_t) &n, sizeof n); 636. if (n > 0) 637. bwrite(fd, (genericptr_t) regions[i]->enter_msg, n); 638. n = regions[i]->leave_msg != NULL ? strlen(regions[i]->leave_msg) : 0; 639. bwrite(fd, (genericptr_t) &n, sizeof n); 640. if (n > 0) 641. bwrite(fd, (genericptr_t) regions[i]->leave_msg, n); 642. bwrite(fd, (genericptr_t) ®ions[i]->ttl, sizeof (short)); 643. bwrite(fd, (genericptr_t) ®ions[i]->expire_f, sizeof (short)); 644. bwrite(fd, (genericptr_t) ®ions[i]->can_enter_f, sizeof (short)); 645. bwrite(fd, (genericptr_t) ®ions[i]->enter_f, sizeof (short)); 646. bwrite(fd, (genericptr_t) ®ions[i]->can_leave_f, sizeof (short)); 647. bwrite(fd, (genericptr_t) ®ions[i]->leave_f, sizeof (short)); 648. bwrite(fd, (genericptr_t) ®ions[i]->inside_f, sizeof (short)); 649. bwrite(fd, (genericptr_t) ®ions[i]->player_flags, sizeof (boolean)); 650. bwrite(fd, (genericptr_t) ®ions[i]->n_monst, sizeof (short)); 651. for (j = 0; j < regions[i]->n_monst; j++) 652. bwrite(fd, (genericptr_t) ®ions[i]->monsters[j], 653. sizeof (unsigned)); 654. bwrite(fd, (genericptr_t) ®ions[i]->visible, sizeof (boolean)); 655. bwrite(fd, (genericptr_t) ®ions[i]->glyph, sizeof (int)); 656. bwrite(fd, (genericptr_t) ®ions[i]->arg, sizeof (genericptr_t)); 657. } 658. 659. skip_lots: 660. if (release_data(mode)) 661. clear_regions(); 662. } 663.
rest_regions
664. void 665. rest_regions(fd, ghostly) 666. int fd; 667. boolean ghostly; /* If a bones file restore */ 668. { 669. int i, j; 670. unsigned n; 671. long tmstamp; 672. char *msg_buf; 673. 674. clear_regions(); /* Just for security */ 675. mread(fd, (genericptr_t) &tmstamp, sizeof (tmstamp)); 676. if (ghostly) tmstamp = 0; 677. else tmstamp = (moves - tmstamp); 678. mread(fd, (genericptr_t) &n_regions, sizeof (n_regions)); 679. max_regions = n_regions; 680. if (n_regions > 0) 681. regions = (NhRegion **) alloc(sizeof (NhRegion *) * n_regions); 682. for (i = 0; i < n_regions; i++) { 683. regions[i] = (NhRegion *) alloc(sizeof (NhRegion)); 684. mread(fd, (genericptr_t) ®ions[i]->bounding_box, sizeof (NhRect)); 685. mread(fd, (genericptr_t) ®ions[i]->nrects, sizeof (short)); 686. 687. if (regions[i]->nrects > 0) 688. regions[i]->rects = (NhRect *) 689. alloc(sizeof (NhRect) * regions[i]->nrects); 690. for (j = 0; j < regions[i]->nrects; j++) 691. mread(fd, (genericptr_t) ®ions[i]->rects[j], sizeof (NhRect)); 692. mread(fd, (genericptr_t) ®ions[i]->attach_2_u, sizeof (boolean)); 693. mread(fd, (genericptr_t) ®ions[i]->attach_2_m, sizeof (unsigned)); 694. 695. mread(fd, (genericptr_t) &n, sizeof n); 696. if (n > 0) { 697. msg_buf = (char *) alloc(n + 1); 698. mread(fd, (genericptr_t) msg_buf, n); 699. msg_buf[n] = '\0'; 700. regions[i]->enter_msg = (const char *) msg_buf; 701. } else 702. regions[i]->enter_msg = NULL; 703. 704. mread(fd, (genericptr_t) &n, sizeof n); 705. if (n > 0) { 706. msg_buf = (char *) alloc(n + 1); 707. mread(fd, (genericptr_t) msg_buf, n); 708. msg_buf[n] = '\0'; 709. regions[i]->leave_msg = (const char *) msg_buf; 710. } else 711. regions[i]->leave_msg = NULL; 712. 713. mread(fd, (genericptr_t) ®ions[i]->ttl, sizeof (short)); 714. /* check for expired region */ 715. if (regions[i]->ttl >= 0) 716. regions[i]->ttl = 717. (regions[i]->ttl > tmstamp) ? regions[i]->ttl - tmstamp : 0; 718. mread(fd, (genericptr_t) ®ions[i]->expire_f, sizeof (short)); 719. mread(fd, (genericptr_t) ®ions[i]->can_enter_f, sizeof (short)); 720. mread(fd, (genericptr_t) ®ions[i]->enter_f, sizeof (short)); 721. mread(fd, (genericptr_t) ®ions[i]->can_leave_f, sizeof (short)); 722. mread(fd, (genericptr_t) ®ions[i]->leave_f, sizeof (short)); 723. mread(fd, (genericptr_t) ®ions[i]->inside_f, sizeof (short)); 724. mread(fd, (genericptr_t) ®ions[i]->player_flags, sizeof (boolean)); 725. if (ghostly) { /* settings pertained to old player */ 726. clear_hero_inside(regions[i]); 727. clear_heros_fault(regions[i]); 728. } 729. mread(fd, (genericptr_t) ®ions[i]->n_monst, sizeof (short)); 730. if (regions[i]->n_monst > 0) 731. regions[i]->monsters = 732. (unsigned *) alloc(sizeof (unsigned) * regions[i]->n_monst); 733. else 734. regions[i]->monsters = NULL; 735. regions[i]->max_monst = regions[i]->n_monst; 736. for (j = 0; j < regions[i]->n_monst; j++) 737. mread(fd, (genericptr_t) ®ions[i]->monsters[j], 738. sizeof (unsigned)); 739. mread(fd, (genericptr_t) ®ions[i]->visible, sizeof (boolean)); 740. mread(fd, (genericptr_t) ®ions[i]->glyph, sizeof (int)); 741. mread(fd, (genericptr_t) ®ions[i]->arg, sizeof (genericptr_t)); 742. } 743. /* remove expired regions, do not trigger the expire_f callback (yet!); 744. also update monster lists if this data is coming from a bones file */ 745. for (i = n_regions - 1; i >= 0; i--) 746. if (regions[i]->ttl == 0) 747. remove_region(regions[i]); 748. else if (ghostly && regions[i]->n_monst > 0) 749. reset_region_mids(regions[i]); 750. } 751.
reset_region_mids
752. /* update monster IDs for region being loaded from bones; `ghostly' implied */ 753. static void 754. reset_region_mids(reg) 755. NhRegion *reg; 756. { 757. int i = 0, n = reg->n_monst; 758. unsigned *mid_list = reg->monsters; 759. 760. while (i < n) 761. if (!lookup_id_mapping(mid_list[i], &mid_list[i])) { 762. /* shrink list to remove missing monster; order doesn't matter */ 763. mid_list[i] = mid_list[--n]; 764. } else { 765. /* move on to next monster */ 766. ++i; 767. } 768. reg->n_monst = n; 769. return; 770. } 771. 772. #if 0
create_msg_region
773. /* not yet used */ 774. 775. /*--------------------------------------------------------------* 776. * * 777. * Create Region with just a message * 778. * * 779. *--------------------------------------------------------------*/ 780. 781. NhRegion * 782. create_msg_region(x, y, w, h, msg_enter, msg_leave) 783. xchar x, y; 784. xchar w, h; 785. const char *msg_enter; 786. const char *msg_leave; 787. { 788. NhRect tmprect; 789. NhRegion *reg = create_region((NhRect *) 0, 0); 790. 791. reg->enter_msg = msg_enter; 792. reg->leave_msg = msg_leave; 793. tmprect.lx = x; 794. tmprect.ly = y; 795. tmprect.hx = x + w; 796. tmprect.hy = y + h; 797. add_rect_to_reg(reg, &tmprect); 798. reg->ttl = -1; 799. return reg; 800. } 801. 802.
enter_force_field
803. /*--------------------------------------------------------------* 804. * * 805. * Force Field Related Code * 806. * (unused yet) * 807. *--------------------------------------------------------------*/ 808. 809. boolean 810. enter_force_field(p1, p2) 811. genericptr_t p1; 812. genericptr_t p2; 813. { 814. struct monst *mtmp; 815. 816. if (p2 == NULL) { /* That means the player */ 817. if (!Blind) 818. You("bump into %s. Ouch!", 819. Hallucination ? "an invisible tree" : 820. "some kind of invisible wall"); 821. else 822. pline("Ouch!"); 823. } else { 824. mtmp = (struct monst *) p2; 825. if (canseemon(mtmp)) 826. pline("%s bumps into %s!", Monnam(mtmp), something); 827. } 828. return FALSE; 829. } 830.
create_force_field
831. NhRegion * 832. create_force_field(x, y, radius, ttl) 833. xchar x, y; 834. int radius, ttl; 835. { 836. int i; 837. NhRegion *ff; 838. int nrect; 839. NhRect tmprect; 840. 841. ff = create_region((NhRect *) 0, 0); 842. nrect = radius; 843. tmprect.lx = x; 844. tmprect.hx = x; 845. tmprect.ly = y - (radius - 1); 846. tmprect.hy = y + (radius - 1); 847. for (i = 0; i < nrect; i++) { 848. add_rect_to_reg(ff, &tmprect); 849. tmprect.lx--; 850. tmprect.hx++; 851. tmprect.ly++; 852. tmprect.hy--; 853. } 854. ff->ttl = ttl; 855. if (!in_mklev && !flags.mon_moving) 856. set_heros_fault(ff); /* assume player has created it */ 857. /* ff->can_enter_f = enter_force_field; */ 858. /* ff->can_leave_f = enter_force_field; */ 859. add_region(ff); 860. return ff; 861. } 862. 863. #endif /*0*/ 864.
expire_gas_cloud
865. /*--------------------------------------------------------------* 866. * * 867. * Gas cloud related code * 868. * * 869. *--------------------------------------------------------------*/ 870. 871. /* 872. * Here is an example of an expire function that may prolong 873. * region life after some mods... 874. */ 875. boolean 876. expire_gas_cloud(p1, p2) 877. genericptr_t p1; 878. genericptr_t p2; 879. { 880. NhRegion *reg; 881. int damage; 882. 883. reg = (NhRegion *) p1; 884. damage = (int) reg->arg; 885. 886. /* If it was a thick cloud, it dissipates a little first */ 887. if (damage >= 5) { 888. damage /= 2; /* It dissipates, let's do less damage */ 889. reg->arg = (genericptr_t) damage; 890. reg->ttl = 2; /* Here's the trick : reset ttl */ 891. return FALSE; /* THEN return FALSE, means "still there" */ 892. } 893. return TRUE; /* OK, it's gone, you can free it! */ 894. } 895.
inside_gas_cloud
896. boolean 897. inside_gas_cloud(p1, p2) 898. genericptr_t p1; 899. genericptr_t p2; 900. { 901. NhRegion *reg; 902. struct monst *mtmp; 903. int dam; 904. 905. reg = (NhRegion *) p1; 906. dam = (int) reg->arg; 907. if (p2 == NULL) { /* This means *YOU* Bozo! */ 908. if (nonliving(youmonst.data) || Breathless) 909. return FALSE; 910. if (!Blind) 911. make_blinded(1L, FALSE); 912. if (!Poison_resistance) { 913. pline("%s is burning your %s!", Something, makeplural(body_part(LUNG))); 914. You("cough and spit blood!"); 915. losehp(rnd(dam) + 5, "gas cloud", KILLED_BY_AN); 916. return FALSE; 917. } else { 918. You("cough!"); 919. return FALSE; 920. } 921. } else { /* A monster is inside the cloud */ 922. mtmp = (struct monst *) p2; 923. 924. /* Non living and non breathing monsters are not concerned */ 925. if (!nonliving(mtmp->data) && !breathless(mtmp->data)) { 926. if (cansee(mtmp->mx, mtmp->my)) 927. pline("%s coughs!", Monnam(mtmp)); 928. setmangry(mtmp); 929. if (haseyes(mtmp->data) && mtmp->mcansee) { 930. mtmp->mblinded = 1; 931. mtmp->mcansee = 0; 932. } 933. if (resists_poison(mtmp)) 934. return FALSE; 935. mtmp->mhp -= rnd(dam) + 5; 936. if (mtmp->mhp <= 0) { 937. if (heros_fault(reg)) 938. killed(mtmp); 939. else 940. monkilled(mtmp, "gas cloud", AD_DRST); 941. if (mtmp->mhp <= 0) { /* not lifesaved */ 942. return TRUE; 943. } 944. } 945. } 946. } 947. return FALSE; /* Monster is still alive */ 948. } 949.
create_gas_cloud
950. NhRegion * 951. create_gas_cloud(x, y, radius, damage) 952. xchar x, y; 953. int radius; 954. int damage; 955. { 956. NhRegion *cloud; 957. int i, nrect; 958. NhRect tmprect; 959. 960. cloud = create_region((NhRect *) 0, 0); 961. nrect = radius; 962. tmprect.lx = x; 963. tmprect.hx = x; 964. tmprect.ly = y - (radius - 1); 965. tmprect.hy = y + (radius - 1); 966. for (i = 0; i < nrect; i++) { 967. add_rect_to_reg(cloud, &tmprect); 968. tmprect.lx--; 969. tmprect.hx++; 970. tmprect.ly++; 971. tmprect.hy--; 972. } 973. cloud->ttl = rn1(3,4); 974. if (!in_mklev && !flags.mon_moving) 975. set_heros_fault(cloud); /* assume player has created it */ 976. cloud->inside_f = INSIDE_GAS_CLOUD; 977. cloud->expire_f = EXPIRE_GAS_CLOUD; 978. cloud->arg = (genericptr_t) damage; 979. cloud->visible = TRUE; 980. cloud->glyph = cmap_to_glyph(S_cloud); 981. add_region(cloud); 982. return cloud; 983. } 984. 985. /*region.c*/