About: Source:SLASH'EM 0.0.7E7F2/region.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to region.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/region.c#line123]], for example. The latest source code for vanilla NetHack is at Source code.

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