About: Source:NetHack 3.1.0/display.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 display.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/display.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code

AttributesValues
rdfs:label
  • Source:NetHack 3.1.0/display.c
rdfs:comment
  • Below is the full text to display.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/display.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • Below is the full text to display.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/display.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)display.c 3.1 92/10/25 */ 2. /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ 3. /* and Dave Cohrs, 1990. */ 4. /* NetHack may be freely redistributed. See license for details. */ 5. 6. /* 7. * THE NEW DISPLAY CODE 8. * 9. * The old display code has been broken up into three parts: vision, display, 10. * and drawing. Vision decides what locations can and cannot be physically 11. * seen by the hero. Display decides _what_ is displayed at a given location. 12. * Drawing decides _how_ to draw a monster, fountain, sword, etc. 13. * 14. * The display system uses information from the vision system to decide 15. * what to draw at a given location. The routines for the vision system 16. * can be found in vision.c and vision.h. The routines for display can 17. * be found in this file (display.c) and display.h. The drawing routines 18. * are part of the window port. See doc/window.doc for the drawing 19. * interface. 20. * 21. * The display system deals with an abstraction called a glyph. Anything 22. * that could possibly be displayed has a unique glyph identifier. 23. * 24. * What is seen on the screen is a combination of what the hero remembers 25. * and what the hero currently sees. Objects and dungeon features (walls 26. * doors, etc) are remembered when out of sight. Monsters and temporary 27. * effects are not remembered. Each location on the level has an 28. * associated glyph. This is the hero's _memory_ of what he or she has 29. * seen there before. 30. * 31. * Display rules: 32. * 33. * If the location is in sight, display in order: 34. * visible monsters 35. * visible objects 36. * known traps 37. * background 38. * 39. * If the location is out of sight, display in order: 40. * sensed monsters (telepathy) 41. * memory 42. * 43. * 44. * 45. * Here is a list of the major routines in this file to be used externally: 46. * 47. * newsym 48. * 49. * Possibly update the screen location (x,y). This is the workhorse routine. 50. * It is always correct --- where correct means following the in-sight/out- 51. * of-sight rules. **Most of the code should use this routine.** This 52. * routine updates the map and displays monsters. 53. * 54. * 55. * map_background 56. * map_object 57. * map_trap 58. * unmap_object 59. * 60. * If you absolutely must override the in-sight/out-of-sight rules, there 61. * are two possibilities. First, you can mess with vision to force the 62. * location in sight then use newsym(), or you can use the map_* routines. 63. * The first has not been tried [no need] and the second is used in the 64. * detect routines --- detect object, magic mapping, etc. The map_* 65. * routines *change* what the hero remembers. All changes made by these 66. * routines will be sticky --- they will survive screen redraws. Do *not* 67. * use these for things that only temporarily change the screen. These 68. * routines are also used directly by newsym(). unmap_object is used to 69. * clear a remembered object when/if detection reveals it isn't there. 70. * 71. * 72. * show_glyph 73. * 74. * This is direct (no processing in between) buffered access to the screen. 75. * Temporary screen effects are run through this and its companion, 76. * flush_screen(). There is yet a lower level routine, print_glyph(), 77. * but this is unbuffered and graphic dependent (i.e. it must be surrounded 78. * by graphic set-up and tear-down routines). Do not use print_glyph(). 79. * 80. * 81. * see_monsters 82. * see_objects 83. * 84. * These are only used when something affects all of the monsters or 85. * objects. For objects, the only thing is hallucination. For monsters, 86. * there are hallucination and changing from/to blindness, etc. 87. * 88. * 89. * tmp_at 90. * 91. * This is a useful interface for displaying temporary items on the screen. 92. * Its interface is different than previously, so look at it carefully. 93. * 94. * 95. * 96. * Parts of the rm structure that are used: 97. * 98. * typ - What is really there. 99. * glyph - What the hero remembers. This will never be a monster. 100. * Monsters "float" above this. 101. * lit - True if the position is lit. An optimization for 102. * lit/unlit rooms. 103. * waslit - True if the position was *remembered* as lit. 104. * seen - Set to true when the location is seen or felt as it really 105. * is. This is used primarily for walls, which look like stone 106. * if seen from the outside of a room. However, this is 107. * also used as a guide for blind heros. If the hero has 108. * seen or felt a room feature underneath a boulder, when the 109. * boulder is moved, the hero should see it again. This is 110. * also used as an indicator for unmapping detected objects. 111. * 112. * doormask - Additional information for the typ field. 113. * horizontal - Indicates whether the wall or door is horizontal or 114. * vertical. 115. */ 116. #include "hack.h" 117. 118. static void FDECL(display_monster,(XCHAR_P,XCHAR_P,struct monst *,int,XCHAR_P)); 119. static int FDECL(swallow_to_glyph, (int, int)); 120. 121. #ifdef INVISIBLE_OBJECTS 122. /* 123. * vobj_at() 124. * 125. * Returns a pointer to an object if the hero can see an object at the 126. * given location. This takes care of invisible objects. NOTE, this 127. * assumes that the hero is not blind and on top of the object pile. 128. * It does NOT take into account that the location is out of sight, or, 129. * say, one can see blessed, etc. 130. */ 131. struct obj * 132. vobj_at(x,y) 133. xchar x,y; 134. { 135. register struct obj *obj = level.objects[x][y]; 136. 137. while (obj) { 138. if (!obj->oinvis || See_invisible) return obj; 139. obj = obj->nexthere; 140. } 141. return ((struct obj *) 0); 142. } 143. #endif /* else vobj_at() is defined in display.h */ 144. 145. /* 146. * The routines map_background(), map_object(), and map_trap() could just 147. * as easily be: 148. * 149. * map_glyph(x,y,glyph,show) 150. * 151. * Which is called with the xx_to_glyph() in the call. Then I can get 152. * rid of 3 routines that don't do very much anyway. And then stop 153. * having to create fake objects and traps. However, I am reluctant to 154. * make this change. 155. */ 156. 157. /* 158. * map_background() 159. * 160. * Make the real background part of our map. This routine assumes that 161. * the hero can physically see the location. Update the screen if directed. 162. */ 163. void 164. map_background(x, y, show) 165. register xchar x,y; 166. register int show; 167. { 168. register int glyph = back_to_glyph(x,y); 169. 170. if (level.flags.hero_memory) 171. levl[x][y].glyph = glyph; 172. if (show) show_glyph(x,y, glyph); 173. } 174. 175. /* 176. * map_trap() 177. * 178. * Map the trap and print it out if directed. This routine assumes that the 179. * hero can physically see the location. 180. */ 181. void 182. map_trap(trap, show) 183. register struct trap *trap; 184. register int show; 185. { 186. register int x = trap->tx, y = trap->ty; 187. register int glyph = trap_to_glyph(trap); 188. 189. if (level.flags.hero_memory) 190. levl[x][y].glyph = glyph; 191. if (show) show_glyph(x, y, glyph); 192. } 193. 194. /* 195. * map_object() 196. * 197. * Map the given object. This routine assumes that the hero can physically 198. * see the location of the object. Update the screen if directed. 199. */ 200. void 201. map_object(obj, show) 202. register struct obj *obj; 203. register int show; 204. { 205. register int x = obj->ox, y = obj->oy; 206. register int glyph = obj_to_glyph(obj); 207. 208. if (level.flags.hero_memory) 209. levl[x][y].glyph = glyph; 210. if (show) show_glyph(x, y, glyph); 211. } 212. 213. /* 214. * unmap_object() 215. * 216. * Remove something from the map when detection reveals that it isn't 217. * there any more. Replace it with background or known trap, but not 218. * with any other remembered object. No need to update the display; 219. * a full update is imminent. 220. * 221. * This isn't quite correct due to overloading of the seen bit. But 222. * it works well enough for now. 223. */ 224. void 225. unmap_object(x, y) 226. register int x, y; 227. { 228. register struct trap *trap; 229. 230. if (!level.flags.hero_memory) return; 231. 232. if ((trap = t_at(x,y)) != 0 && trap->tseen && !covers_traps(x,y)) 233. map_trap(trap, 0); 234. else if (levl[x][y].seen) { 235. struct rm *lev = &levl[x][y]; 236. 237. map_background(x, y, 0); 238. 239. /* turn remembered dark room squares dark */ 240. if (!lev->waslit && lev->glyph == cmap_to_glyph(S_room) && 241. lev->typ == ROOM) 242. lev->glyph = cmap_to_glyph(S_stone); 243. } else 244. levl[x][y].glyph = cmap_to_glyph(S_stone); /* default val */ 245. } 246. 247. 248. /* 249. * map_location() 250. * 251. * Make whatever at this location show up. This is only for non-living 252. * things. This will not handle feeling invisible objects correctly. 253. */ 254. #define map_location(x,y,show) \ 255. { \ 256. register struct obj *obj; \ 257. register struct trap *trap; \ 258. \ 259. if ((obj = vobj_at(x,y)) && !covers_objects(x,y)) \ 260. map_object(obj,show); \ 261. else if ((trap = t_at(x,y)) && trap->tseen && !covers_traps(x,y)) \ 262. map_trap(trap,show); \ 263. else \ 264. map_background(x,y,show); \ 265. } 266. 267. 268. /* 269. * display_monster() 270. * 271. * Note that this is *not* a map_XXXX() function! Monsters sort of float 272. * above everything. 273. * 274. * Yuck. Display body parts by recognizing that the display position is 275. * not the same as the monster position. Currently the only body part is 276. * a worm tail. 277. * 278. */ 279. static void 280. display_monster(x, y, mon, in_sight, worm_tail) 281. register xchar x, y; /* display position */ 282. register struct monst *mon; /* monster to display */ 283. int in_sight; /* TRUE if the monster is physically seen */ 284. register xchar worm_tail; /* mon is actually a worm tail */ 285. { 286. register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING); 287. register int sensed = mon_mimic && 288. (Protection_from_shape_changers || sensemon(mon)); 289. 290. /* 291. * We must do the mimic check first. If the mimic is mimicing something, 292. * and the location is in sight, we have to change the hero's memory 293. * so that when the position is out of sight, the hero remembers what 294. * the mimic was mimicing. 295. */ 296. 297. if (mon_mimic && in_sight) { 298. switch (mon->m_ap_type) { 299. default: 300. impossible("display_monster: bad m_ap_type value [ = %d ]", 301. (int) mon->m_ap_type); 302. case M_AP_NOTHING: 303. show_glyph(x, y, mon_to_glyph(mon)); 304. break; 305. 306. case M_AP_FURNITURE: { 307. /* 308. * This is a poor man's version of map_background(). I can't 309. * use map_background() because we are overriding what is in 310. * the 'typ' field. Maybe have map_background()'s parameters 311. * be (x,y,glyph) instead of just (x,y). 312. * 313. * mappearance is currently set to an S_ index value in 314. * makemon.c. 315. */ 316. register int glyph = cmap_to_glyph(mon->mappearance); 317. levl[x][y].glyph = glyph; 318. if (!sensed) show_glyph(x,y, glyph); 319. break; 320. } 321. 322. case M_AP_OBJECT: { 323. struct obj obj; /* Make a fake object to send */ 324. /* to map_object(). */ 325. obj.ox = x; 326. obj.oy = y; 327. obj.otyp = mon->mappearance; 328. obj.corpsenm = PM_TENGU; /* if mimicing a corpse */ 329. map_object(&obj,!sensed); 330. break; 331. } 332. 333. case M_AP_MONSTER: 334. show_glyph(x,y, monnum_to_glyph(what_mon(mon->mappearance))); 335. break; 336. } 337. 338. } 339. 340. /* If the mimic is unsucessfully mimicing something, display the monster */ 341. if (!mon_mimic || sensed) { 342. if (mon->mtame) { 343. if (worm_tail) 344. show_glyph(x,y, petnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))); 345. else 346. show_glyph(x,y, pet_to_glyph(mon)); 347. } else { 348. if (worm_tail) 349. show_glyph(x,y, monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))); 350. else 351. show_glyph(x,y, mon_to_glyph(mon)); 352. } 353. } 354. } 355. 356. /* 357. * feel_location() 358. * 359. * Feel the given location. This assumes that the hero is blind and that 360. * the given position is either the hero's or one of the eight squares 361. * adjacent to the hero (except for a boulder push). 362. */ 363. void 364. feel_location(x, y) 365. xchar x, y; 366. { 367. struct rm *lev = &(levl[x][y]); 368. struct obj *boulder; 369. register struct monst *mon; 370. 371. /* The hero can't feel non pool locations while under water. */ 372. if (Underwater && !Is_waterlevel(&u.uz) && ! is_pool(x,y)) 373. return; 374. 375. /* If the hero is not in a corridor, then she will feel the wall as a */ 376. /* wall. It doesn't matter if the hero is levitating or not. */ 377. if ((IS_WALL(lev->typ) || lev->typ == SDOOR) && 378. levl[u.ux][u.uy].typ != CORR) 379. lev->seen = 1; 380. 381. if (Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) { 382. /* 383. * Levitation Rules. It is assumed that the hero can feel the state 384. * of the walls around herself and can tell if she is in a corridor, 385. * room, or doorway. Boulders are felt because they are large enough. 386. * Anything else is unknown because the hero can't reach the ground. 387. * This makes things difficult. 388. * 389. * Check (and display) in order: 390. * 391. * + Stone, walls, and closed doors. 392. * + Boulders. [see a boulder before a doorway] 393. * + Doors. 394. * + Room/water positions 395. * + Everything else (hallways!) 396. */ 397. if (IS_ROCK(lev->typ) || (IS_DOOR(lev->typ) && 398. (lev->doormask & (D_LOCKED | D_CLOSED)))) { 399. map_background(x, y, 1); 400. } else if (boulder = sobj_at(BOULDER,x,y)) { 401. map_object(boulder, 1); 402. } else if (IS_DOOR(lev->typ)) { 403. map_background(x, y, 1); 404. } else if (IS_ROOM(lev->typ) || IS_POOL(lev->typ)) { 405. /* 406. * An open room or water location. Normally we wouldn't touch 407. * this, but we have to get rid of remembered boulder symbols. 408. * This will only occur in rare occations when the hero goes 409. * blind and doesn't find a boulder where expected (something 410. * came along and picked it up). We know that there is not a 411. * boulder at this location. Show fountains, pools, etc. 412. * underneath if already seen. Otherwise, show the appropriate 413. * floor symbol. 414. * 415. * This isn't quite correct. If the boulder was on top of some 416. * other objects they should be seen once the boulder is removed. 417. * However, we have no way of knowing that what is there now 418. * was there then. So we let the hero have a lapse of memory. 419. * We could also just display what is currently on the top of the 420. * object stack (if anything). 421. */ 422. if (lev->glyph == objnum_to_glyph(BOULDER)) { 423. if (lev->typ != ROOM && lev->seen) { 424. map_background(x, y, 1); 425. } else { 426. lev->glyph = lev->waslit ? cmap_to_glyph(S_room) : 427. cmap_to_glyph(S_stone); 428. show_glyph(x,y,lev->glyph); 429. } 430. } 431. } else { 432. /* We feel it (I think hallways are the only things left). */ 433. map_background(x, y, 1); 434. /* Corridors are never felt as lit (unless remembered that way) */ 435. /* (lit_corridor only). */ 436. if (lev->typ == CORR && 437. lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit) 438. show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr)); 439. } 440. } else { 441. map_location(x, y, 1); 442. 443. if (Punished) { 444. /* 445. * A ball or chain is only felt if it is first on the object 446. * location list. Otherwise, we need to clear the felt bit --- 447. * something has been dropped on the ball/chain. If the bit is 448. * not cleared, then when the ball/chain is moved it will drop 449. * the wrong glyph. 450. */ 451. if (uchain->ox == x && uchain->oy == y) { 452. if (level.objects[x][y] == uchain) 453. u.bc_felt |= BC_CHAIN; 454. else 455. u.bc_felt &= ~BC_CHAIN; /* do not feel the chain */ 456. } 457. if (!carried(uball) && uball->ox == x && uball->oy == y) { 458. if (level.objects[x][y] == uball) 459. u.bc_felt |= BC_BALL; 460. else 461. u.bc_felt &= ~BC_BALL; /* do not feel the ball */ 462. } 463. } 464. 465. /* Floor spaces are dark if unlit. Corridors are dark if unlit. */ 466. if (lev->typ == ROOM && 467. lev->glyph == cmap_to_glyph(S_room) && !lev->waslit) 468. show_glyph(x,y, lev->glyph = cmap_to_glyph(S_stone)); 469. else if (lev->typ == CORR && 470. lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit) 471. show_glyph(x,y, lev->glyph = cmap_to_glyph(S_corr)); 472. } 473. /* draw monster on top if we can sense it */ 474. if ((x != u.ux || y != u.uy) && (mon = m_at(x,y)) && sensemon(mon)) 475. display_monster(x,y,mon,1,((x != mon->mx) || (y != mon->my))); 476. } 477. 478. /* 479. * newsym() 480. * 481. * Possibly put a new glyph at the given location. 482. */ 483. void 484. newsym(x,y) 485. register xchar x,y; 486. { 487. register struct monst *mon; 488. register struct rm *lev = &(levl[x][y]); 489. register int see_it; 490. register xchar worm_tail; 491. 492. /* only permit updating the hero when swallowed */ 493. if (u.uswallow) { 494. if (x == u.ux && y == u.uy) display_self(); 495. return; 496. } 497. if (Underwater && !Is_waterlevel(&u.uz)) { 498. /* don't do anything unless (x,y) is an adjacent underwater position */ 499. int dx, dy; 500. if (!is_pool(x,y)) return; 501. dx = x - u.ux; if (dx < 0) dx = -dx; 502. dy = y - u.uy; if (dy < 0) dy = -dy; 503. if (dx > 1 || dy > 1) return; 504. } 505. 506. /* Can physically see the location. */ 507. if (cansee(x,y)) { 508. lev->waslit = (lev->lit!=0); /* remember lit condition */ 509. 510. if (x == u.ux && y == u.uy) { 511. if (canseeself()) { 512. map_location(x,y,0); /* map *under* self */ 513. display_self(); 514. } else 515. /* we can see what is there */ 516. map_location(x,y,1); 517. } 518. else if ((mon = m_at(x,y)) && 519. ((see_it = mon_visible(mon)) || sensemon(mon))) { 520. map_location(x,y,0); /* map under the monster */ 521. worm_tail = ((x != mon->mx) || (y != mon->my)); 522. display_monster(x,y,mon,see_it,worm_tail); 523. } 524. else 525. map_location(x,y,1); /* map the location */ 526. } 527. 528. /* Can't see the location. */ 529. else { 530. if (x == u.ux && y == u.uy) { 531. feel_location(u.ux, u.uy); /* forces an update */ 532. 533. if (canseeself()) display_self(); 534. } 535. else if ((mon = m_at(x,y)) && sensemon(mon) && 536. !((x != mon->mx) || (y != mon->my))) { 537. /* Monsters are printed every time. */ 538. display_monster(x,y,mon,0,0); 539. } 540. /* 541. * If the location is remembered as being both dark (waslit is false) 542. * and lit (glyph is a lit room or lit corridor) then it was either: 543. * 544. * (1) A dark location that the hero could see through night 545. * vision. 546. * 547. * (2) Darkened while out of the hero's sight. This can happen 548. * when cursed scroll of light is read. 549. * 550. * In either case, we have to manually correct the hero's memory to 551. * match waslit. Deciding when to change waslit is non-trivial. 552. * 553. * Note: If flags.lit_corridor is set, then corridors act like room 554. * squares. That is, they light up if in night vision range. 555. * If flags.lit_corridor is not set, then corridors will 556. * remain dark unless lit by a light spell. 557. * 558. * These checks and changes must be here and not in back_to_glyph(). 559. * They are dependent on the position being out of sight. 560. */ 561. else if (!lev->waslit) { 562. if (flags.lit_corridor && lev->glyph == cmap_to_glyph(S_litcorr) && 563. lev->typ == CORR) 564. show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr)); 565. else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM) 566. show_glyph(x, y, lev->glyph = cmap_to_glyph(S_stone)); 567. else 568. goto show_mem; 569. } else { 570. show_mem: 571. show_glyph(x, y, lev->glyph); 572. } 573. } 574. } 575. 576. 577. /* 578. * shieldeff() 579. * 580. * Put magic shield pyrotechnics at the given location. This *could* be 581. * pulled into a platform dependent routine for fancier graphics if desired. 582. */ 583. void 584. shieldeff(x,y) 585. xchar x,y; 586. { 587. register int i; 588. 589. if (cansee(x,y)) { /* Don't see anything if can't see the location */ 590. for (i = 0; i < SHIELD_COUNT; i++) { 591. show_glyph(x, y, cmap_to_glyph(shield_static[i])); 592. flush_screen(1); /* make sure the glyph shows up */ 593. delay_output(); 594. } 595. newsym(x,y); /* restore the old information */ 596. } 597. } 598. 599. 600. /* 601. * tmp_at() 602. * 603. * Temporarily place glyphs on the screen. Do not call delay_output(). It 604. * is up to the caller to decide if it wants to wait [presently, everyone 605. * but explode() wants to delay]. 606. * 607. * Call: 608. * (DISP_BEAM, glyph) open, initialize glyph 609. * (DISP_FLASH, glyph) open, initialize glyph 610. * (DISP_CHANGE, glyph) change glyph 611. * (DISP_END, 0) close & clean up (second argument doesn't 612. * matter) 613. * (x, y) display the glyph at the location 614. * 615. * DISP_BEAM - Display the given glyph at each location, but do not erase 616. * any until the close call. 617. * DISP_FLASH - Display the given glyph at each location, but erase the 618. * previous location's glyph. 619. */ 620. void 621. tmp_at(x, y) 622. int x, y; 623. { 624. static coord saved[COLNO]; /* prev positions, only for DISP_BEAM */ 625. static int sidx = 0; /* index of saved previous positions */ 626. static int sx = -1, sy; /* previous position, only for DISP_FLASH */ 627. static int status; /* either DISP_BEAM or DISP_FLASH */ 628. static int glyph; /* glyph to use when printing */ 629. 630. switch (x) { 631. case DISP_BEAM: 632. case DISP_FLASH: 633. status = x; 634. glyph = y; 635. flush_screen(0); /* flush buffered glyphs */ 636. break; 637. 638. case DISP_CHANGE: 639. glyph = y; 640. break; 641. 642. case DISP_END: 643. if (status == DISP_BEAM) { 644. register int i; 645. 646. /* Erase (reset) from source to end */ 647. for (i = 0; i < sidx; i++) 648. newsym(saved[i].x,saved[i].y); 649. sidx = 0; 650. 651. } else if (sx >= 0) { /* DISP_FLASH (called at least once) */ 652. newsym(sx,sy); /* reset the location */ 653. sx = -1; /* reset sx to an illegal pos for next time */ 654. } 655. break; 656. 657. default: /* do it */ 658. if (!cansee(x,y)) break; 659. 660. if (status == DISP_BEAM) { 661. saved[sidx ].x = x; /* save pos for later erasing */ 662. saved[sidx++].y = y; 663. } 664. 665. else { /* DISP_FLASH */ 666. if (sx >= 0) /* not first call */ 667. newsym(sx,sy); /* update the old position */ 668. 669. sx = x; /* save previous pos for next call */ 670. sy = y; 671. } 672. 673. show_glyph(x,y,glyph); /* show it */ 674. flush_screen(0); /* make sure it shows up */ 675. break; 676. } /* end case */ 677. } 678. 679. 680. /* 681. * swallowed() 682. * 683. * The hero is swallowed. Show a special graphics sequence for this. This 684. * bypasses all of the display routines and messes with buffered screen 685. * directly. This method works because both vision and display check for 686. * being swallowed. 687. */ 688. void 689. swallowed(first) 690. int first; 691. { 692. static xchar lastx, lasty; /* last swallowed position */ 693. int swallower; 694. 695. if (first) 696. cls(); 697. else { 698. register int x, y; 699. 700. /* Clear old location */ 701. for (y = lasty-1; y <= lasty+1; y++) 702. if(isok(lastx,y)) { 703. for (x = lastx-1; x <= lastx+1; x++) 704. show_glyph(x,y,cmap_to_glyph(S_stone)); 705. } 706. } 707. 708. swallower = monsndx(u.ustuck->data); 709. /* 710. * Display the hero surrounded by the monster's stomach. 711. */ 712. if(isok(u.ux, u.uy-1)) { 713. show_glyph(u.ux-1, u.uy-1, swallow_to_glyph(swallower, S_sw_tl)); 714. show_glyph(u.ux , u.uy-1, swallow_to_glyph(swallower, S_sw_tc)); 715. show_glyph(u.ux+1, u.uy-1, swallow_to_glyph(swallower, S_sw_tr)); 716. } 717. 718. show_glyph(u.ux-1, u.uy , swallow_to_glyph(swallower, S_sw_ml)); 719. display_self(); 720. show_glyph(u.ux+1, u.uy , swallow_to_glyph(swallower, S_sw_mr)); 721. 722. if(isok(u.ux, u.uy+1)) { 723. show_glyph(u.ux-1, u.uy+1, swallow_to_glyph(swallower, S_sw_bl)); 724. show_glyph(u.ux , u.uy+1, swallow_to_glyph(swallower, S_sw_bc)); 725. show_glyph(u.ux+1, u.uy+1, swallow_to_glyph(swallower, S_sw_br)); 726. } 727. 728. /* Update the swallowed position. */ 729. lastx = u.ux; 730. lasty = u.uy; 731. } 732. 733. /* 734. * under_water() 735. * 736. * Similar to swallowed() in operation. Shows hero when underwater 737. * except when in water level. Special routines exist for that. 738. */ 739. void 740. under_water(mode) 741. int mode; 742. { 743. static xchar lastx, lasty; 744. static boolean dela; 745. register int x, y; 746. 747. /* swallowing has a higher precedence than under water */ 748. if (Is_waterlevel(&u.uz) || u.uswallow) return; 749. 750. /* full update */ 751. if (mode == 1 || dela) { 752. cls(); 753. dela = FALSE; 754. } 755. /* delayed full update */ 756. else if (mode == 2) { 757. dela = TRUE; 758. return; 759. } 760. /* limited update */ 761. else { 762. for (y = lasty-1; y <= lasty+1; y++) 763. for (x = lastx-1; x <= lastx+1; x++) 764. if (isok(x,y)) 765. show_glyph(x,y,cmap_to_glyph(S_stone)); 766. } 767. for (x = u.ux-1; x <= u.ux+1; x++) 768. for (y = u.uy-1; y <= u.uy+1; y++) 769. if (isok(x,y) && is_pool(x,y)) { 770. if (Blind && !(x == u.ux && y == u.uy)) 771. show_glyph(x,y,cmap_to_glyph(S_stone)); 772. else 773. newsym(x,y); 774. } 775. lastx = u.ux; 776. lasty = u.uy; 777. } 778. 779. 780. /* ========================================================================= */ 781. 782. /* 783. * Loop through all of the monsters and update them. Called when: 784. * + going blind & telepathic 785. * + regaining sight & telepathic 786. * + hallucinating 787. * + doing a full screen redraw 788. * + see invisible times out or a ring of see invisible is taken off 789. * + when a potion of see invisible is quaffed or a ring of see 790. * invisible is put on 791. * + gaining telepathy when blind [givit() in eat.c, pleased() in pray.c] 792. * + losing telepathy while blind [xkilled() in mon.c, attrcurse() in 793. * sit.c] 794. */ 795. void 796. see_monsters() 797. { 798. register struct monst *mon; 799. for (mon = fmon; mon; mon = mon->nmon) { 800. newsym(mon->mx,mon->my); 801. if (mon->wormno) see_wsegs(mon); 802. } 803. } 804. 805. /* 806. * Block/unblock light depending on what a mimic is mimicing and if it's 807. * invisible or not. Should be called only when the state of See_invisible 808. * changes. 809. */ 810. void 811. set_mimic_blocking() 812. { 813. register struct monst *mon; 814. for (mon = fmon; mon; mon = mon->nmon) 815. if(mon->minvis && 816. ((mon->m_ap_type == M_AP_FURNITURE && 817. (mon->mappearance == S_vcdoor || mon->mappearance == S_hcdoor))|| 818. (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER))) { 819. if(See_invisible) 820. block_point(mon->mx, mon->my); 821. else 822. unblock_point(mon->mx, mon->my); 823. } 824. } 825. 826. /* 827. * Loop through all of the object *locations* and update them. Called when 828. * + hallucinating. 829. */ 830. void 831. see_objects() 832. { 833. register struct obj *obj; 834. for(obj = fobj; obj; obj = obj->nobj) 835. if (vobj_at(obj->ox,obj->oy) == obj) newsym(obj->ox, obj->oy); 836. } 837. 838. /* 839. * Put the cursor on the hero. Flush all accumulated glyphs before doing it. 840. */ 841. void 842. curs_on_u() 843. { 844. flush_screen(1); /* Flush waiting glyphs & put cursor on hero */ 845. } 846. 847. int 848. doredraw() 849. { 850. docrt(); 851. return 0; 852. } 853. 854. void 855. docrt() 856. { 857. register int x,y; 858. register struct rm *lev; 859. 860. if (!u.ux) return; /* display isn't ready yet */ 861. 862. if (u.uswallow) { 863. swallowed(1); 864. return; 865. } 866. if (Underwater && !Is_waterlevel(&u.uz)) { 867. under_water(1); 868. return; 869. } 870. 871. /* shut down vision */ 872. vision_recalc(2); 873. 874. /* 875. * This routine assumes that cls() does the following: 876. * + fills the physical screen with the symbol for rock 877. * + clears the glyph buffer 878. */ 879. cls(); 880. 881. /* display memory */ 882. for (x = 1; x < COLNO; x++) { 883. lev = &levl[x][0]; 884. for (y = 0; y < ROWNO; y++, lev++) 885. if (lev->glyph != cmap_to_glyph(S_stone)) 886. show_glyph(x,y,lev->glyph); 887. } 888. 889. /* see what is to be seen */ 890. vision_recalc(0); 891. 892. /* overlay with monsters */ 893. see_monsters(); 894. 895. flags.botlx = 1; /* force a redraw of the bottom line */ 896. } 897. 898. 899. /* ========================================================================= */ 900. /* Glyph Buffering (3rd screen) ============================================ */ 901. 902. typedef struct { 903. xchar new; /* perhaps move this bit into the rm strucure. */ 904. int glyph; 905. } gbuf_entry; 906. 907. static gbuf_entry gbuf[ROWNO][COLNO]; 908. static char gbuf_start[ROWNO]; 909. static char gbuf_stop[ROWNO]; 910. 911. /* 912. * Store the glyph in the 3rd screen for later flushing. 913. */ 914. void 915. show_glyph(x,y,glyph) 916. xchar x,y; 917. int glyph; 918. { 919. /* 920. * Check for bad positions and glyphs. 921. */ 922. if (x <= 0 || x >= COLNO || y < 0 || y >= ROWNO) { 923. const char *text; 924. int offset; 925. 926. /* column 0 is invalid, but it's often used as a flag, so ignore it */ 927. if (x == 0) return; 928. 929. /* 930. * This assumes an ordering of the offsets. See display.h for 931. * the definition. 932. */ 933. if (glyph >= GLYPH_SWALLOW_OFF) { /* swallow border */ 934. text = "swallow border"; offset = glyph - GLYPH_SWALLOW_OFF; 935. }else if (glyph >= GLYPH_ZAP_OFF) { /* zap beam */ 936. text = "zap beam"; offset = glyph - GLYPH_ZAP_OFF; 937. } else if (glyph >= GLYPH_CMAP_OFF) { /* cmap */ 938. text = "cmap_index"; offset = glyph - GLYPH_CMAP_OFF; 939. } else if (glyph >= GLYPH_TRAP_OFF) { /* trap */ 940. text = "trap"; offset = glyph - GLYPH_TRAP_OFF; 941. } else if (glyph >= GLYPH_OBJ_OFF) { /* object */ 942. text = "object"; offset = glyph - GLYPH_OBJ_OFF; 943. } else if (glyph >= GLYPH_BODY_OFF) { /* a corpse */ 944. text = "corpse"; offset = glyph - GLYPH_BODY_OFF; 945. } else { /* a monster */ 946. text = "monster"; offset = glyph; 947. } 948. 949. impossible("show_glyph: bad pos %d %d with glyph %d [%s %d].", 950. x, y, glyph, text, offset); 951. return; 952. } 953. 954. if (glyph >= MAX_GLYPH) { 955. impossible("show_glyph: bad glyph %d [max %d] at (%d,%d).", 956. glyph, MAX_GLYPH, x, y); 957. return; 958. } 959. 960. if (gbuf[y][x].glyph != glyph) { 961. gbuf[y][x].glyph = glyph; 962. gbuf[y][x].new = 1; 963. if (gbuf_start[y] > x) gbuf_start[y] = x; 964. if (gbuf_stop[y] < x) gbuf_stop[y] = x; 965. } 966. } 967. 968. 969. /* 970. * Reset the changed glyph borders so that none of the 3rd screen has 971. * changed. 972. */ 973. #define reset_glyph_bbox() \ 974. { \ 975. int i; \ 976. \ 977. for (i = 0; i < ROWNO; i++) { \ 978. gbuf_start[i] = COLNO-1; \ 979. gbuf_stop[i] = 0; \ 980. } \ 981. } 982. 983. 984. static gbuf_entry nul_gbuf = { 0, cmap_to_glyph(S_stone) }; 985. /* 986. * Turn the 3rd screen into stone. 987. */ 988. void 989. clear_glyph_buffer() 990. { 991. register int x, y; 992. register gbuf_entry *gptr; 993. 994. for (y = 0; y < ROWNO; y++) { 995. gptr = &gbuf[y][0]; 996. for (x = COLNO; x; x--) { 997. *gptr++ = nul_gbuf; 998. } 999. } 1000. reset_glyph_bbox(); 1001. } 1002. 1003. /* 1004. * Assumes that the indicated positions are filled with S_stone glyphs. 1005. */ 1006. void 1007. row_refresh(start,stop,y) 1008. int start,stop,y; 1009. { 1010. register int x; 1011. 1012. for (x = start; x <= stop; x++) 1013. if (gbuf[y][x].glyph != cmap_to_glyph(S_stone)) 1014. print_glyph(WIN_MAP,x,y,gbuf[y][x].glyph); 1015. } 1016. 1017. void 1018. cls() 1019. { 1020. display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */ 1021. flags.botlx = 1; /* force update of botl window */ 1022. clear_nhwindow(WIN_MAP); /* clear physical screen */ 1023. 1024. clear_glyph_buffer(); /* this is sort of an extra effort, but OK */ 1025. } 1026. 1027. /* 1028. * Synch the third screen with the display. 1029. */ 1030. void 1031. flush_screen(cursor_on_u) 1032. int cursor_on_u; 1033. { 1034. /* Prevent infinite loops on errors: 1035. * flush_screen->print_glyph->impossible->pline->flush_screen 1036. */ 1037. static boolean flushing = 0; 1038. register int x,y; 1039. 1040. if (flushing) return; /* if already flushing then return */ 1041. flushing = 1; 1042. 1043. for (y = 0; y < ROWNO; y++) { 1044. register gbuf_entry *gptr = &gbuf[y][x = gbuf_start[y]]; 1045. for (; x <= gbuf_stop[y]; gptr++, x++) 1046. if (gptr->new) { 1047. print_glyph(WIN_MAP,x,y,gptr->glyph); 1048. gptr->new = 0; 1049. } 1050. } 1051. 1052. if (cursor_on_u) curs(WIN_MAP, u.ux,u.uy); /* move cursor to the hero */ 1053. display_nhwindow(WIN_MAP, FALSE); 1054. reset_glyph_bbox(); 1055. flushing = 0; 1056. if(flags.botl || flags.botlx) bot(); 1057. } 1058. 1059. /* ========================================================================= */ 1060. 1061. /* 1062. * back_to_glyph() 1063. * 1064. * Use the information in the rm structure at the given position to create 1065. * a glyph of a background. 1066. * 1067. * I had to add a field in the rm structure (horizontal) so that we knew 1068. * if open doors and secret doors were horizontal or vertical. Previously, 1069. * the screen symbol had the horizontal/vertical information set at 1070. * level generation time. 1071. * 1072. * I used the 'ladder' field (really doormask) for deciding if stairwells 1073. * were up or down. I didn't want to check the upstairs and dnstairs 1074. * variables. 1075. */ 1076. int 1077. back_to_glyph(x,y) 1078. xchar x,y; 1079. { 1080. int idx; 1081. struct rm *ptr = &(levl[x][y]); 1082. 1083. switch (ptr->typ) { 1084. case SCORR: 1085. case STONE: idx = S_stone; break; 1086. case ROOM: idx = S_room; break; 1087. case CORR: 1088. idx = (ptr->waslit || flags.lit_corridor) ? S_litcorr : S_corr; 1089. break; 1090. case HWALL: idx = ptr->seen ? S_hwall : S_stone; break; 1091. case VWALL: idx = ptr->seen ? S_vwall : S_stone; break; 1092. case TLCORNER: idx = ptr->seen ? S_tlcorn : S_stone; break; 1093. case TRCORNER: idx = ptr->seen ? S_trcorn : S_stone; break; 1094. case BLCORNER: idx = ptr->seen ? S_blcorn : S_stone; break; 1095. case BRCORNER: idx = ptr->seen ? S_brcorn : S_stone; break; 1096. case CROSSWALL: idx = ptr->seen ? S_crwall : S_stone; break; 1097. case TUWALL: idx = ptr->seen ? S_tuwall : S_stone; break; 1098. case TDWALL: idx = ptr->seen ? S_tdwall : S_stone; break; 1099. case TLWALL: idx = ptr->seen ? S_tlwall : S_stone; break; 1100. case TRWALL: idx = ptr->seen ? S_trwall : S_stone; break; 1101. case SDOOR: 1102. if (ptr->seen) 1103. idx = (ptr->horizontal) ? S_hwall : S_vwall; 1104. else 1105. idx = S_stone; 1106. break; 1107. case DOOR: 1108. if (ptr->doormask) { 1109. if (ptr->doormask & D_BROKEN) 1110. idx = S_ndoor; 1111. else if (ptr->doormask & D_ISOPEN) 1112. idx = (ptr->horizontal) ? S_hodoor : S_vodoor; 1113. else /* else is closed */ 1114. idx = (ptr->horizontal) ? S_hcdoor : S_vcdoor; 1115. } else 1116. idx = S_ndoor; 1117. break; 1118. case POOL: 1119. case MOAT: idx = S_pool; break; 1120. case STAIRS: 1121. idx = (ptr->ladder & LA_DOWN) ? S_dnstair : S_upstair; 1122. break; 1123. case LADDER: 1124. idx = (ptr->ladder & LA_DOWN) ? S_dnladder : S_upladder; 1125. break; 1126. case FOUNTAIN: idx = S_fountain; break; 1127. case SINK: idx = S_sink; break; 1128. case ALTAR: idx = S_altar; break; 1129. case THRONE: idx = S_throne; break; 1130. case LAVAPOOL: idx = S_lava; break; 1131. case ICE: idx = S_ice; break; 1132. case AIR: idx = S_air; break; 1133. case CLOUD: idx = S_cloud; break; 1134. case WATER: idx = S_water; break; 1135. case DBWALL: 1136. idx = (ptr->horizontal) ? S_hcdbridge : S_vcdbridge; 1137. break; 1138. case DRAWBRIDGE_UP: 1139. switch(ptr->drawbridgemask & DB_UNDER) { 1140. case DB_MOAT: idx = S_pool; break; 1141. case DB_LAVA: idx = S_lava; break; 1142. case DB_ICE: idx = S_ice; break; 1143. case DB_FLOOR: idx = S_room; break; 1144. default: 1145. impossible("Strange db-under: %d", 1146. ptr->drawbridgemask & DB_UNDER); 1147. idx = S_room; /* something is better than nothing */ 1148. break; 1149. } 1150. break; 1151. case DRAWBRIDGE_DOWN: 1152. idx = (ptr->horizontal) ? S_hodbridge : S_vodbridge; 1153. break; 1154. default: 1155. impossible("back_to_glyph: unknown level type [ = %d ]",ptr->typ); 1156. idx = S_room; 1157. break; 1158. } 1159. 1160. return cmap_to_glyph(idx); 1161. } 1162. 1163. 1164. /* 1165. * swallow_to_glyph() 1166. * 1167. * Convert a monster number and a swallow location into the correct glyph. 1168. * If you don't want a patchwork monster while hallucinating, decide on 1169. * a random monster in swallowed() and don't use what_mon() here. 1170. */ 1171. static int 1172. swallow_to_glyph(mnum, loc) 1173. int mnum; 1174. int loc; 1175. { 1176. if (loc < S_sw_tl || S_sw_br < loc) { 1177. impossible("swallow_to_glyph: bad swallow location"); 1178. loc = S_sw_br; 1179. } 1180. return ((int) (what_mon(mnum)<<3) | (loc - S_sw_tl)) + GLYPH_SWALLOW_OFF; 1181. } 1182. 1183. 1184. 1185. /* 1186. * zapdir_to_glyph() 1187. * 1188. * Change the given zap direction and beam type into a glyph. Each beam 1189. * type has four glyphs, one for each of the symbols below. The order of 1190. * the zap symbols [0-3] as defined in rm.h are: 1191. * 1192. * | S_vbeam ( 0, 1) or ( 0,-1) 1193. * - S_hbeam ( 1, 0) or (-1, 0) 1194. * \ S_lslant ( 1, 1) or (-1,-1) 1195. * / S_rslant (-1, 1) or ( 1,-1) 1196. */ 1197. int 1198. zapdir_to_glyph(dx, dy, beam_type) 1199. register int dx, dy; 1200. int beam_type; 1201. { 1202. if (beam_type >= NUM_ZAP) { 1203. impossible("zapdir_to_glyph: illegal beam type"); 1204. beam_type = 0; 1205. } 1206. dx = (dx == dy) ? 2 : (dx && dy) ? 3 : dx ? 1 : 0; 1207. 1208. return ((int) ((beam_type << 2) | dx)) + GLYPH_ZAP_OFF; 1209. } 1210. 1211. 1212. /* 1213. * Utility routine for dowhatis() used to find out the glyph displayed at 1214. * the location. This isn't necessarily the same as the glyph in the levl 1215. * structure, so we must check the "third screen". 1216. */ 1217. int 1218. glyph_at(x, y) 1219. xchar x,y; 1220. { 1221. if(x < 0 || y < 0 || x >= COLNO || y >= ROWNO) 1222. return cmap_to_glyph(S_room); /* XXX */ 1223. return gbuf[y][x].glyph; 1224. } 1225. 1226. /*display.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