About: Source:NetHack 3.2.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.2.0. To link to a particular line, write [[NetHack 3.2.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.2.0/display.c
rdfs:comment
  • Below is the full text to display.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2.0. To link to a particular line, write [[NetHack 3.2.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.2 95/02/27 */ 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. * seenv - A vector of bits representing the directions from which the 105. * hero has seen this position. The vector's primary use is 106. * determining how walls are seen. E.g. a wall sometimes looks 107. * like stone on one side, but is seen as a wall from the other. 108. * Other uses are for unmapping detected objects and felt 109. * locations, where we need to know if the hero has ever 110. * seen the location. 111. * flags - Additional information for the typ field. Different for 112. * each typ. 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. static int FDECL(check_pos, (int, int, int)); 122. static boolean FDECL(more_than_one, (int, int, int, int, int)); 123. static int FDECL(set_twall, (int,int, int,int, int,int, int,int)); 124. static int FDECL(set_wall, (int, int, int)); 125. static int FDECL(set_corn, (int,int, int,int, int,int, int,int)); 126. static int FDECL(set_crosswall, (int, int)); 127. static void FDECL(set_seenv, (struct rm *, int, int, int, int)); 128. static void FDECL(t_warn, (struct rm *)); 129. static int FDECL(wall_angle, (struct rm *)); 130. 131. #ifdef INVISIBLE_OBJECTS 132. /* 133. * vobj_at() 134. * 135. * Returns a pointer to an object if the hero can see an object at the 136. * given location. This takes care of invisible objects. NOTE, this 137. * assumes that the hero is not blind and on top of the object pile. 138. * It does NOT take into account that the location is out of sight, or, 139. * say, one can see blessed, etc. 140. */ 141. struct obj * 142. vobj_at(x,y) 143. xchar x,y; 144. { 145. register struct obj *obj = level.objects[x][y]; 146. 147. while (obj) { 148. if (!obj->oinvis || See_invisible) return obj; 149. obj = obj->nexthere; 150. } 151. return ((struct obj *) 0); 152. } 153. #endif /* else vobj_at() is defined in display.h */ 154. 155. /* 156. * The routines map_background(), map_object(), and map_trap() could just 157. * as easily be: 158. * 159. * map_glyph(x,y,glyph,show) 160. * 161. * Which is called with the xx_to_glyph() in the call. Then I can get 162. * rid of 3 routines that don't do very much anyway. And then stop 163. * having to create fake objects and traps. However, I am reluctant to 164. * make this change. 165. */ 166. 167. /* 168. * map_background() 169. * 170. * Make the real background part of our map. This routine assumes that 171. * the hero can physically see the location. Update the screen if directed. 172. */ 173. void 174. map_background(x, y, show) 175. register xchar x,y; 176. register int show; 177. { 178. register int glyph = back_to_glyph(x,y); 179. 180. if (level.flags.hero_memory) 181. levl[x][y].glyph = glyph; 182. if (show) show_glyph(x,y, glyph); 183. } 184. 185. /* 186. * map_trap() 187. * 188. * Map the trap and print it out if directed. This routine assumes that the 189. * hero can physically see the location. 190. */ 191. void 192. map_trap(trap, show) 193. register struct trap *trap; 194. register int show; 195. { 196. register int x = trap->tx, y = trap->ty; 197. register int glyph = trap_to_glyph(trap); 198. 199. if (level.flags.hero_memory) 200. levl[x][y].glyph = glyph; 201. if (show) show_glyph(x, y, glyph); 202. } 203. 204. /* 205. * map_object() 206. * 207. * Map the given object. This routine assumes that the hero can physically 208. * see the location of the object. Update the screen if directed. 209. */ 210. void 211. map_object(obj, show) 212. register struct obj *obj; 213. register int show; 214. { 215. register int x = obj->ox, y = obj->oy; 216. register int glyph = obj_to_glyph(obj); 217. 218. if (level.flags.hero_memory) 219. levl[x][y].glyph = glyph; 220. if (show) show_glyph(x, y, glyph); 221. } 222. 223. /* 224. * unmap_object() 225. * 226. * Remove something from the map when detection reveals that it isn't 227. * there any more. Replace it with background or known trap, but not 228. * with any other remembered object. No need to update the display; 229. * a full update is imminent. 230. */ 231. void 232. unmap_object(x, y) 233. register int x, y; 234. { 235. register struct trap *trap; 236. 237. if (!level.flags.hero_memory) return; 238. 239. if ((trap = t_at(x,y)) != 0 && trap->tseen && !covers_traps(x,y)) 240. map_trap(trap, 0); 241. else if (levl[x][y].seenv) { 242. struct rm *lev = &levl[x][y]; 243. 244. map_background(x, y, 0); 245. 246. /* turn remembered dark room squares dark */ 247. if (!lev->waslit && lev->glyph == cmap_to_glyph(S_room) && 248. lev->typ == ROOM) 249. lev->glyph = cmap_to_glyph(S_stone); 250. } else 251. levl[x][y].glyph = cmap_to_glyph(S_stone); /* default val */ 252. } 253. 254. 255. /* 256. * map_location() 257. * 258. * Make whatever at this location show up. This is only for non-living 259. * things. This will not handle feeling invisible objects correctly. 260. * 261. * Internal to display.c, this is a #define for speed. 262. */ 263. #define _map_location(x,y,show) \ 264. { \ 265. register struct obj *obj; \ 266. register struct trap *trap; \ 267. \ 268. if ((obj = vobj_at(x,y)) && !covers_objects(x,y)) \ 269. map_object(obj,show); \ 270. else if ((trap = t_at(x,y)) && trap->tseen && !covers_traps(x,y)) \ 271. map_trap(trap,show); \ 272. else \ 273. map_background(x,y,show); \ 274. } 275. 276. void map_location(x,y,show) 277. int x, y, show; 278. { 279. _map_location(x,y,show); 280. } 281. 282. 283. /* 284. * display_monster() 285. * 286. * Note that this is *not* a map_XXXX() function! Monsters sort of float 287. * above everything. 288. * 289. * Yuck. Display body parts by recognizing that the display position is 290. * not the same as the monster position. Currently the only body part is 291. * a worm tail. 292. * 293. */ 294. static void 295. display_monster(x, y, mon, in_sight, worm_tail) 296. register xchar x, y; /* display position */ 297. register struct monst *mon; /* monster to display */ 298. int in_sight; /* TRUE if the monster is physically seen */ 299. register xchar worm_tail; /* mon is actually a worm tail */ 300. { 301. register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING); 302. register int sensed = mon_mimic && 303. (Protection_from_shape_changers || sensemon(mon)); 304. 305. /* 306. * We must do the mimic check first. If the mimic is mimicing something, 307. * and the location is in sight, we have to change the hero's memory 308. * so that when the position is out of sight, the hero remembers what 309. * the mimic was mimicing. 310. */ 311. 312. if (mon_mimic && in_sight) { 313. switch (mon->m_ap_type) { 314. default: 315. impossible("display_monster: bad m_ap_type value [ = %d ]", 316. (int) mon->m_ap_type); 317. case M_AP_NOTHING: 318. show_glyph(x, y, mon_to_glyph(mon)); 319. break; 320. 321. case M_AP_FURNITURE: { 322. /* 323. * This is a poor man's version of map_background(). I can't 324. * use map_background() because we are overriding what is in 325. * the 'typ' field. Maybe have map_background()'s parameters 326. * be (x,y,glyph) instead of just (x,y). 327. * 328. * mappearance is currently set to an S_ index value in 329. * makemon.c. 330. */ 331. register int glyph = cmap_to_glyph(mon->mappearance); 332. levl[x][y].glyph = glyph; 333. if (!sensed) show_glyph(x,y, glyph); 334. break; 335. } 336. 337. case M_AP_OBJECT: { 338. struct obj obj; /* Make a fake object to send */ 339. /* to map_object(). */ 340. obj.ox = x; 341. obj.oy = y; 342. obj.otyp = mon->mappearance; 343. obj.corpsenm = PM_TENGU; /* if mimicing a corpse */ 344. map_object(&obj,!sensed); 345. break; 346. } 347. 348. case M_AP_MONSTER: 349. show_glyph(x,y, monnum_to_glyph(what_mon(mon->mappearance))); 350. break; 351. } 352. 353. } 354. 355. /* If the mimic is unsucessfully mimicing something, display the monster */ 356. if (!mon_mimic || sensed) { 357. if (mon->mtame && !Hallucination) { 358. if (worm_tail) 359. show_glyph(x,y, petnum_to_glyph(PM_LONG_WORM_TAIL)); 360. else 361. show_glyph(x,y, pet_to_glyph(mon)); 362. } else { 363. if (worm_tail) 364. show_glyph(x,y, monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))); 365. else 366. show_glyph(x,y, mon_to_glyph(mon)); 367. } 368. } 369. } 370. 371. /* 372. * feel_location() 373. * 374. * Feel the given location. This assumes that the hero is blind and that 375. * the given position is either the hero's or one of the eight squares 376. * adjacent to the hero (except for a boulder push). 377. */ 378. void 379. feel_location(x, y) 380. xchar x, y; 381. { 382. struct rm *lev = &(levl[x][y]); 383. struct obj *boulder; 384. register struct monst *mon; 385. 386. /* The hero can't feel non pool locations while under water. */ 387. if (Underwater && !Is_waterlevel(&u.uz) && ! is_pool(x,y)) 388. return; 389. 390. /* Set the seen vector as if the hero had seen it. It doesn't matter */ 391. /* if the hero is levitating or not. */ 392. set_seenv(lev, u.ux, u.uy, x, y); 393. 394. if (Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) { 395. /* 396. * Levitation Rules. It is assumed that the hero can feel the state 397. * of the walls around herself and can tell if she is in a corridor, 398. * room, or doorway. Boulders are felt because they are large enough. 399. * Anything else is unknown because the hero can't reach the ground. 400. * This makes things difficult. 401. * 402. * Check (and display) in order: 403. * 404. * + Stone, walls, and closed doors. 405. * + Boulders. [see a boulder before a doorway] 406. * + Doors. 407. * + Room/water positions 408. * + Everything else (hallways!) 409. */ 410. if (IS_ROCK(lev->typ) || (IS_DOOR(lev->typ) && 411. (lev->doormask & (D_LOCKED | D_CLOSED)))) { 412. map_background(x, y, 1); 413. } else if ((boulder = sobj_at(BOULDER,x,y)) != 0) { 414. map_object(boulder, 1); 415. } else if (IS_DOOR(lev->typ)) { 416. map_background(x, y, 1); 417. } else if (IS_ROOM(lev->typ) || IS_POOL(lev->typ)) { 418. /* 419. * An open room or water location. Normally we wouldn't touch 420. * this, but we have to get rid of remembered boulder symbols. 421. * This will only occur in rare occations when the hero goes 422. * blind and doesn't find a boulder where expected (something 423. * came along and picked it up). We know that there is not a 424. * boulder at this location. Show fountains, pools, etc. 425. * underneath if already seen. Otherwise, show the appropriate 426. * floor symbol. 427. * 428. * This isn't quite correct. If the boulder was on top of some 429. * other objects they should be seen once the boulder is removed. 430. * However, we have no way of knowing that what is there now 431. * was there then. So we let the hero have a lapse of memory. 432. * We could also just display what is currently on the top of the 433. * object stack (if anything). 434. */ 435. if (lev->glyph == objnum_to_glyph(BOULDER)) { 436. if (lev->typ != ROOM && lev->seenv) { 437. map_background(x, y, 1); 438. } else { 439. lev->glyph = lev->waslit ? cmap_to_glyph(S_room) : 440. cmap_to_glyph(S_stone); 441. show_glyph(x,y,lev->glyph); 442. } 443. } 444. } else { 445. /* We feel it (I think hallways are the only things left). */ 446. map_background(x, y, 1); 447. /* Corridors are never felt as lit (unless remembered that way) */ 448. /* (lit_corridor only). */ 449. if (lev->typ == CORR && 450. lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit) 451. show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr)); 452. } 453. } else { 454. _map_location(x, y, 1); 455. 456. if (Punished) { 457. /* 458. * A ball or chain is only felt if it is first on the object 459. * location list. Otherwise, we need to clear the felt bit --- 460. * something has been dropped on the ball/chain. If the bit is 461. * not cleared, then when the ball/chain is moved it will drop 462. * the wrong glyph. 463. */ 464. if (uchain->ox == x && uchain->oy == y) { 465. if (level.objects[x][y] == uchain) 466. u.bc_felt |= BC_CHAIN; 467. else 468. u.bc_felt &= ~BC_CHAIN; /* do not feel the chain */ 469. } 470. if (!carried(uball) && uball->ox == x && uball->oy == y) { 471. if (level.objects[x][y] == uball) 472. u.bc_felt |= BC_BALL; 473. else 474. u.bc_felt &= ~BC_BALL; /* do not feel the ball */ 475. } 476. } 477. 478. /* Floor spaces are dark if unlit. Corridors are dark if unlit. */ 479. if (lev->typ == ROOM && 480. lev->glyph == cmap_to_glyph(S_room) && !lev->waslit) 481. show_glyph(x,y, lev->glyph = cmap_to_glyph(S_stone)); 482. else if (lev->typ == CORR && 483. lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit) 484. show_glyph(x,y, lev->glyph = cmap_to_glyph(S_corr)); 485. } 486. /* draw monster on top if we can sense it */ 487. if ((x != u.ux || y != u.uy) && (mon = m_at(x,y)) && sensemon(mon)) 488. display_monster(x,y,mon,1,((x != mon->mx) || (y != mon->my))); 489. } 490. 491. /* 492. * newsym() 493. * 494. * Possibly put a new glyph at the given location. 495. */ 496. void 497. newsym(x,y) 498. register int x,y; 499. { 500. register struct monst *mon; 501. register struct rm *lev = &(levl[x][y]); 502. register int see_it; 503. register xchar worm_tail; 504. 505. /* only permit updating the hero when swallowed */ 506. if (u.uswallow) { 507. if (x == u.ux && y == u.uy) display_self(); 508. return; 509. } 510. if (Underwater && !Is_waterlevel(&u.uz)) { 511. /* don't do anything unless (x,y) is an adjacent underwater position */ 512. int dx, dy; 513. if (!is_pool(x,y)) return; 514. dx = x - u.ux; if (dx < 0) dx = -dx; 515. dy = y - u.uy; if (dy < 0) dy = -dy; 516. if (dx > 1 || dy > 1) return; 517. } 518. 519. /* Can physically see the location. */ 520. if (cansee(x,y)) { 521. /* 522. * Don't use templit here: E.g. 523. * 524. * lev->waslit = !!(lev->lit || templit(x,y)); 525. * 526. * Otherwise we have the "light pool" problem, where non-permanently 527. * lit areas just out of sight stay remembered as lit. They should 528. * re-darken. 529. * 530. * Perhaps ALL areas should revert to their "unlit" look when 531. * out of sight. 532. */ 533. lev->waslit = (lev->lit!=0); /* remember lit condition */ 534. 535. if (x == u.ux && y == u.uy) { 536. if (canseeself()) { 537. _map_location(x,y,0); /* map *under* self */ 538. display_self(); 539. } else 540. /* we can see what is there */ 541. _map_location(x,y,1); 542. } 543. else { 544. mon = m_at(x,y); 545. worm_tail = mon && ((x != mon->mx) || (y != mon->my)); 546. if (mon && 547. ((see_it = (worm_tail 548. ? (!mon->minvis || See_invisible) 549. : (mon_visible(mon)) || sensemon(mon))))) { 550. _map_location(x,y,0); /* map under the monster */ 551. display_monster(x,y,mon,see_it,worm_tail); 552. } 553. else 554. _map_location(x,y,1); /* map the location */ 555. } 556. } 557. 558. /* Can't see the location. */ 559. else { 560. if (x == u.ux && y == u.uy) { 561. feel_location(u.ux, u.uy); /* forces an update */ 562. 563. if (canseeself()) display_self(); 564. } 565. else if ((mon = m_at(x,y)) && sensemon(mon) && 566. !((x != mon->mx) || (y != mon->my))) { 567. /* Monsters are printed every time. */ 568. display_monster(x,y,mon,0,0); 569. } 570. /* 571. * If the location is remembered as being both dark (waslit is false) 572. * and lit (glyph is a lit room or lit corridor) then it was either: 573. * 574. * (1) A dark location that the hero could see through night 575. * vision. 576. * 577. * (2) Darkened while out of the hero's sight. This can happen 578. * when cursed scroll of light is read. 579. * 580. * In either case, we have to manually correct the hero's memory to 581. * match waslit. Deciding when to change waslit is non-trivial. 582. * 583. * Note: If flags.lit_corridor is set, then corridors act like room 584. * squares. That is, they light up if in night vision range. 585. * If flags.lit_corridor is not set, then corridors will 586. * remain dark unless lit by a light spell. 587. * 588. * These checks and changes must be here and not in back_to_glyph(). 589. * They are dependent on the position being out of sight. 590. */ 591. else if (!lev->waslit) { 592. if (flags.lit_corridor && lev->glyph == cmap_to_glyph(S_litcorr) && 593. lev->typ == CORR) 594. show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr)); 595. else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM) 596. show_glyph(x, y, lev->glyph = cmap_to_glyph(S_stone)); 597. else 598. goto show_mem; 599. } else { 600. show_mem: 601. show_glyph(x, y, lev->glyph); 602. } 603. } 604. } 605. 606. 607. /* 608. * shieldeff() 609. * 610. * Put magic shield pyrotechnics at the given location. This *could* be 611. * pulled into a platform dependent routine for fancier graphics if desired. 612. */ 613. void 614. shieldeff(x,y) 615. xchar x,y; 616. { 617. register int i; 618. 619. if (cansee(x,y)) { /* Don't see anything if can't see the location */ 620. for (i = 0; i < SHIELD_COUNT; i++) { 621. show_glyph(x, y, cmap_to_glyph(shield_static[i])); 622. flush_screen(1); /* make sure the glyph shows up */ 623. delay_output(); 624. } 625. newsym(x,y); /* restore the old information */ 626. } 627. } 628. 629. 630. /* 631. * tmp_at() 632. * 633. * Temporarily place glyphs on the screen. Do not call delay_output(). It 634. * is up to the caller to decide if it wants to wait [presently, everyone 635. * but explode() wants to delay]. 636. * 637. * Call: 638. * (DISP_BEAM, glyph) open, initialize glyph 639. * (DISP_FLASH, glyph) open, initialize glyph 640. * (DISP_ALWAYS, glyph) open, initialize glyph 641. * (DISP_CHANGE, glyph) change glyph 642. * (DISP_END, 0) close & clean up (second argument doesn't 643. * matter) 644. * (x, y) display the glyph at the location 645. * 646. * DISP_BEAM - Display the given glyph at each location, but do not erase 647. * any until the close call. 648. * DISP_FLASH - Display the given glyph at each location, but erase the 649. * previous location's glyph. 650. * DISP_ALWAYS- Like DISP_FLASH, but vision is not taken into account. 651. */ 652. void 653. tmp_at(x, y) 654. int x, y; 655. { 656. static coord saved[COLNO]; /* prev positions, only for DISP_BEAM */ 657. static int sidx = 0; /* index of saved previous positions */ 658. static int sx = -1, sy; /* previous position, only for DISP_FLASH */ 659. static int status; /* either DISP_BEAM or DISP_FLASH */ 660. static int glyph; /* glyph to use when printing */ 661. 662. switch (x) { 663. case DISP_BEAM: 664. case DISP_FLASH: 665. case DISP_ALWAYS: 666. status = x; 667. glyph = y; 668. flush_screen(0); /* flush buffered glyphs */ 669. break; 670. 671. case DISP_CHANGE: 672. glyph = y; 673. break; 674. 675. case DISP_END: 676. if (status == DISP_BEAM) { 677. register int i; 678. 679. /* Erase (reset) from source to end */ 680. for (i = 0; i < sidx; i++) 681. newsym(saved[i].x,saved[i].y); 682. sidx = 0; 683. 684. } else if (sx >= 0) { /* DISP_FLASH/ALWAYS (called at least once) */ 685. newsym(sx,sy); /* reset the location */ 686. sx = -1; /* reset sx to an illegal pos for next time */ 687. } 688. break; 689. 690. default: /* do it */ 691. if (!cansee(x,y) && status != DISP_ALWAYS) break; 692. 693. if (status == DISP_BEAM) { 694. saved[sidx ].x = x; /* save pos for later erasing */ 695. saved[sidx++].y = y; 696. } 697. 698. else { /* DISP_FLASH/MISC */ 699. if (sx >= 0) /* not first call */ 700. newsym(sx,sy); /* update the old position */ 701. 702. sx = x; /* save previous pos for next call */ 703. sy = y; 704. } 705. 706. show_glyph(x,y,glyph); /* show it */ 707. flush_screen(0); /* make sure it shows up */ 708. break; 709. } /* end case */ 710. } 711. 712. 713. /* 714. * swallowed() 715. * 716. * The hero is swallowed. Show a special graphics sequence for this. This 717. * bypasses all of the display routines and messes with buffered screen 718. * directly. This method works because both vision and display check for 719. * being swallowed. 720. */ 721. void 722. swallowed(first) 723. int first; 724. { 725. static xchar lastx, lasty; /* last swallowed position */ 726. int swallower, left_ok, rght_ok; 727. 728. if (first) 729. cls(); 730. else { 731. register int x, y; 732. 733. /* Clear old location */ 734. for (y = lasty-1; y <= lasty+1; y++) 735. for (x = lastx-1; x <= lastx+1; x++) 736. if (isok(x,y)) show_glyph(x,y,cmap_to_glyph(S_stone)); 737. } 738. 739. swallower = monsndx(u.ustuck->data); 740. /* assume isok(u.ux,u.uy) */ 741. left_ok = isok(u.ux-1,u.uy); 742. rght_ok = isok(u.ux+1,u.uy); 743. /* 744. * Display the hero surrounded by the monster's stomach. 745. */ 746. if(isok(u.ux, u.uy-1)) { 747. if (left_ok) 748. show_glyph(u.ux-1, u.uy-1, swallow_to_glyph(swallower, S_sw_tl)); 749. show_glyph(u.ux , u.uy-1, swallow_to_glyph(swallower, S_sw_tc)); 750. if (rght_ok) 751. show_glyph(u.ux+1, u.uy-1, swallow_to_glyph(swallower, S_sw_tr)); 752. } 753. 754. if (left_ok) 755. show_glyph(u.ux-1, u.uy , swallow_to_glyph(swallower, S_sw_ml)); 756. display_self(); 757. if (rght_ok) 758. show_glyph(u.ux+1, u.uy , swallow_to_glyph(swallower, S_sw_mr)); 759. 760. if(isok(u.ux, u.uy+1)) { 761. if (left_ok) 762. show_glyph(u.ux-1, u.uy+1, swallow_to_glyph(swallower, S_sw_bl)); 763. show_glyph(u.ux , u.uy+1, swallow_to_glyph(swallower, S_sw_bc)); 764. if (rght_ok) 765. show_glyph(u.ux+1, u.uy+1, swallow_to_glyph(swallower, S_sw_br)); 766. } 767. 768. /* Update the swallowed position. */ 769. lastx = u.ux; 770. lasty = u.uy; 771. } 772. 773. /* 774. * under_water() 775. * 776. * Similar to swallowed() in operation. Shows hero when underwater 777. * except when in water level. Special routines exist for that. 778. */ 779. void 780. under_water(mode) 781. int mode; 782. { 783. static xchar lastx, lasty; 784. static boolean dela; 785. register int x, y; 786. 787. /* swallowing has a higher precedence than under water */ 788. if (Is_waterlevel(&u.uz) || u.uswallow) return; 789. 790. /* full update */ 791. if (mode == 1 || dela) { 792. cls(); 793. dela = FALSE; 794. } 795. /* delayed full update */ 796. else if (mode == 2) { 797. dela = TRUE; 798. return; 799. } 800. /* limited update */ 801. else { 802. for (y = lasty-1; y <= lasty+1; y++) 803. for (x = lastx-1; x <= lastx+1; x++) 804. if (isok(x,y)) 805. show_glyph(x,y,cmap_to_glyph(S_stone)); 806. } 807. for (x = u.ux-1; x <= u.ux+1; x++) 808. for (y = u.uy-1; y <= u.uy+1; y++) 809. if (isok(x,y) && is_pool(x,y)) { 810. if (Blind && !(x == u.ux && y == u.uy)) 811. show_glyph(x,y,cmap_to_glyph(S_stone)); 812. else 813. newsym(x,y); 814. } 815. lastx = u.ux; 816. lasty = u.uy; 817. } 818. 819. /* 820. * under_ground() 821. * 822. * Very restricted display. You can only see yourself. 823. */ 824. void 825. under_ground(mode) 826. int mode; 827. { 828. static boolean dela; 829. 830. /* swallowing has a higher precedence than under ground */ 831. if (u.uswallow) return; 832. 833. /* full update */ 834. if (mode == 1 || dela) { 835. cls(); 836. dela = FALSE; 837. } 838. /* delayed full update */ 839. else if (mode == 2) { 840. dela = TRUE; 841. return; 842. } 843. /* limited update */ 844. else 845. newsym(u.ux,u.uy); 846. } 847. 848. 849. /* ========================================================================= */ 850. 851. /* 852. * Loop through all of the monsters and update them. Called when: 853. * + going blind & telepathic 854. * + regaining sight & telepathic 855. * + hallucinating 856. * + doing a full screen redraw 857. * + see invisible times out or a ring of see invisible is taken off 858. * + when a potion of see invisible is quaffed or a ring of see 859. * invisible is put on 860. * + gaining telepathy when blind [givit() in eat.c, pleased() in pray.c] 861. * + losing telepathy while blind [xkilled() in mon.c, attrcurse() in 862. * sit.c] 863. */ 864. void 865. see_monsters() 866. { 867. register struct monst *mon; 868. for (mon = fmon; mon; mon = mon->nmon) { 869. newsym(mon->mx,mon->my); 870. if (mon->wormno) see_wsegs(mon); 871. } 872. } 873. 874. /* 875. * Block/unblock light depending on what a mimic is mimicing and if it's 876. * invisible or not. Should be called only when the state of See_invisible 877. * changes. 878. */ 879. void 880. set_mimic_blocking() 881. { 882. register struct monst *mon; 883. for (mon = fmon; mon; mon = mon->nmon) 884. if(mon->minvis && 885. ((mon->m_ap_type == M_AP_FURNITURE && 886. (mon->mappearance == S_vcdoor || mon->mappearance == S_hcdoor))|| 887. (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER))) { 888. if(See_invisible) 889. block_point(mon->mx, mon->my); 890. else 891. unblock_point(mon->mx, mon->my); 892. } 893. } 894. 895. /* 896. * Loop through all of the object *locations* and update them. Called when 897. * + hallucinating. 898. */ 899. void 900. see_objects() 901. { 902. register struct obj *obj; 903. for(obj = fobj; obj; obj = obj->nobj) 904. if (vobj_at(obj->ox,obj->oy) == obj) newsym(obj->ox, obj->oy); 905. } 906. 907. /* 908. * Put the cursor on the hero. Flush all accumulated glyphs before doing it. 909. */ 910. void 911. curs_on_u() 912. { 913. flush_screen(1); /* Flush waiting glyphs & put cursor on hero */ 914. } 915. 916. int 917. doredraw() 918. { 919. docrt(); 920. return 0; 921. } 922. 923. void 924. docrt() 925. { 926. register int x,y; 927. register struct rm *lev; 928. 929. if (!u.ux) return; /* display isn't ready yet */ 930. 931. if (u.uswallow) { 932. swallowed(1); 933. return; 934. } 935. if (Underwater && !Is_waterlevel(&u.uz)) { 936. under_water(1); 937. return; 938. } 939. if (u.uburied) { 940. under_ground(1); 941. return; 942. } 943. 944. /* shut down vision */ 945. vision_recalc(2); 946. 947. /* 948. * This routine assumes that cls() does the following: 949. * + fills the physical screen with the symbol for rock 950. * + clears the glyph buffer 951. */ 952. cls(); 953. 954. /* display memory */ 955. for (x = 1; x < COLNO; x++) { 956. lev = &levl[x][0]; 957. for (y = 0; y < ROWNO; y++, lev++) 958. if (lev->glyph != cmap_to_glyph(S_stone)) 959. show_glyph(x,y,lev->glyph); 960. } 961. 962. /* see what is to be seen */ 963. vision_recalc(0); 964. 965. /* overlay with monsters */ 966. see_monsters(); 967. 968. flags.botlx = 1; /* force a redraw of the bottom line */ 969. } 970. 971. 972. /* ========================================================================= */ 973. /* Glyph Buffering (3rd screen) ============================================ */ 974. 975. typedef struct { 976. xchar new; /* perhaps move this bit into the rm strucure. */ 977. int glyph; 978. } gbuf_entry; 979. 980. static gbuf_entry gbuf[ROWNO][COLNO]; 981. static char gbuf_start[ROWNO]; 982. static char gbuf_stop[ROWNO]; 983. 984. /* 985. * Store the glyph in the 3rd screen for later flushing. 986. */ 987. void 988. show_glyph(x,y,glyph) 989. int x, y, glyph; 990. { 991. /* 992. * Check for bad positions and glyphs. 993. */ 994. if (x <= 0 || x >= COLNO || y < 0 || y >= ROWNO) { 995. const char *text; 996. int offset; 997. 998. /* column 0 is invalid, but it's often used as a flag, so ignore it */ 999. if (x == 0) return; 1000. 1001. /* 1002. * This assumes an ordering of the offsets. See display.h for 1003. * the definition. 1004. */ 1005. if (glyph >= GLYPH_SWALLOW_OFF) { /* swallow border */ 1006. text = "swallow border"; offset = glyph - GLYPH_SWALLOW_OFF; 1007. }else if (glyph >= GLYPH_ZAP_OFF) { /* zap beam */ 1008. text = "zap beam"; offset = glyph - GLYPH_ZAP_OFF; 1009. } else if (glyph >= GLYPH_CMAP_OFF) { /* cmap */ 1010. text = "cmap_index"; offset = glyph - GLYPH_CMAP_OFF; 1011. } else if (glyph >= GLYPH_OBJ_OFF) { /* object */ 1012. text = "object"; offset = glyph - GLYPH_OBJ_OFF; 1013. } else if (glyph >= GLYPH_BODY_OFF) { /* a corpse */ 1014. text = "corpse"; offset = glyph - GLYPH_BODY_OFF; 1015. } else if (glyph >= GLYPH_PET_OFF) { /* a pet */ 1016. text = "pet"; offset = glyph - GLYPH_PET_OFF; 1017. } else { /* a monster */ 1018. text = "monster"; offset = glyph; 1019. } 1020. 1021. impossible("show_glyph: bad pos %d %d with glyph %d [%s %d].", 1022. x, y, glyph, text, offset); 1023. return; 1024. } 1025. 1026. if (glyph >= MAX_GLYPH) { 1027. impossible("show_glyph: bad glyph %d [max %d] at (%d,%d).", 1028. glyph, MAX_GLYPH, x, y); 1029. return; 1030. } 1031. 1032. if (gbuf[y][x].glyph != glyph) { 1033. gbuf[y][x].glyph = glyph; 1034. gbuf[y][x].new = 1; 1035. if (gbuf_start[y] > x) gbuf_start[y] = x; 1036. if (gbuf_stop[y] < x) gbuf_stop[y] = x; 1037. } 1038. } 1039. 1040. 1041. /* 1042. * Reset the changed glyph borders so that none of the 3rd screen has 1043. * changed. 1044. */ 1045. #define reset_glyph_bbox() \ 1046. { \ 1047. int i; \ 1048. \ 1049. for (i = 0; i < ROWNO; i++) { \ 1050. gbuf_start[i] = COLNO-1; \ 1051. gbuf_stop[i] = 0; \ 1052. } \ 1053. } 1054. 1055. 1056. static gbuf_entry nul_gbuf = { 0, cmap_to_glyph(S_stone) }; 1057. /* 1058. * Turn the 3rd screen into stone. 1059. */ 1060. void 1061. clear_glyph_buffer() 1062. { 1063. register int x, y; 1064. register gbuf_entry *gptr; 1065. 1066. for (y = 0; y < ROWNO; y++) { 1067. gptr = &gbuf[y][0]; 1068. for (x = COLNO; x; x--) { 1069. *gptr++ = nul_gbuf; 1070. } 1071. } 1072. reset_glyph_bbox(); 1073. } 1074. 1075. /* 1076. * Assumes that the indicated positions are filled with S_stone glyphs. 1077. */ 1078. void 1079. row_refresh(start,stop,y) 1080. int start,stop,y; 1081. { 1082. register int x; 1083. 1084. for (x = start; x <= stop; x++) 1085. if (gbuf[y][x].glyph != cmap_to_glyph(S_stone)) 1086. print_glyph(WIN_MAP,x,y,gbuf[y][x].glyph); 1087. } 1088. 1089. void 1090. cls() 1091. { 1092. display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */ 1093. flags.botlx = 1; /* force update of botl window */ 1094. clear_nhwindow(WIN_MAP); /* clear physical screen */ 1095. 1096. clear_glyph_buffer(); /* this is sort of an extra effort, but OK */ 1097. } 1098. 1099. /* 1100. * Synch the third screen with the display. 1101. */ 1102. void 1103. flush_screen(cursor_on_u) 1104. int cursor_on_u; 1105. { 1106. /* Prevent infinite loops on errors: 1107. * flush_screen->print_glyph->impossible->pline->flush_screen 1108. */ 1109. static boolean flushing = 0; 1110. register int x,y; 1111. 1112. if (flushing) return; /* if already flushing then return */ 1113. flushing = 1; 1114. 1115. for (y = 0; y < ROWNO; y++) { 1116. register gbuf_entry *gptr = &gbuf[y][x = gbuf_start[y]]; 1117. for (; x <= gbuf_stop[y]; gptr++, x++) 1118. if (gptr->new) { 1119. print_glyph(WIN_MAP,x,y,gptr->glyph); 1120. gptr->new = 0; 1121. } 1122. } 1123. 1124. if (cursor_on_u) curs(WIN_MAP, u.ux,u.uy); /* move cursor to the hero */ 1125. display_nhwindow(WIN_MAP, FALSE); 1126. reset_glyph_bbox(); 1127. flushing = 0; 1128. if(flags.botl || flags.botlx) bot(); 1129. } 1130. 1131. /* ========================================================================= */ 1132. 1133. /* 1134. * back_to_glyph() 1135. * 1136. * Use the information in the rm structure at the given position to create 1137. * a glyph of a background. 1138. * 1139. * I had to add a field in the rm structure (horizontal) so that we knew 1140. * if open doors and secret doors were horizontal or vertical. Previously, 1141. * the screen symbol had the horizontal/vertical information set at 1142. * level generation time. 1143. * 1144. * I used the 'ladder' field (really doormask) for deciding if stairwells 1145. * were up or down. I didn't want to check the upstairs and dnstairs 1146. * variables. 1147. */ 1148. int 1149. back_to_glyph(x,y) 1150. xchar x,y; 1151. { 1152. int idx; 1153. struct rm *ptr = &(levl[x][y]); 1154. 1155. switch (ptr->typ) { 1156. case SCORR: 1157. case STONE: idx = S_stone; break; 1158. case ROOM: idx = S_room; break; 1159. case CORR: 1160. idx = (ptr->waslit || flags.lit_corridor) ? S_litcorr : S_corr; 1161. break; 1162. case HWALL: 1163. case VWALL: 1164. case TLCORNER: 1165. case TRCORNER: 1166. case BLCORNER: 1167. case BRCORNER: 1168. case CROSSWALL: 1169. case TUWALL: 1170. case TDWALL: 1171. case TLWALL: 1172. case TRWALL: 1173. case SDOOR: 1174. idx = ptr->seenv ? wall_angle(ptr) : S_stone; 1175. break; 1176. case DOOR: 1177. if (ptr->doormask) { 1178. if (ptr->doormask & D_BROKEN) 1179. idx = S_ndoor; 1180. else if (ptr->doormask & D_ISOPEN) 1181. idx = (ptr->horizontal) ? S_hodoor : S_vodoor; 1182. else /* else is closed */ 1183. idx = (ptr->horizontal) ? S_hcdoor : S_vcdoor; 1184. } else 1185. idx = S_ndoor; 1186. break; 1187. case POOL: 1188. case MOAT: idx = S_pool; break; 1189. case STAIRS: 1190. idx = (ptr->ladder & LA_DOWN) ? S_dnstair : S_upstair; 1191. break; 1192. case LADDER: 1193. idx = (ptr->ladder & LA_DOWN) ? S_dnladder : S_upladder; 1194. break; 1195. case FOUNTAIN: idx = S_fountain; break; 1196. case SINK: idx = S_sink; break; 1197. case ALTAR: idx = S_altar; break; 1198. case THRONE: idx = S_throne; break; 1199. case LAVAPOOL: idx = S_lava; break; 1200. case ICE: idx = S_ice; break; 1201. case AIR: idx = S_air; break; 1202. case CLOUD: idx = S_cloud; break; 1203. case WATER: idx = S_water; break; 1204. case DBWALL: 1205. idx = (ptr->horizontal) ? S_hcdbridge : S_vcdbridge; 1206. break; 1207. case DRAWBRIDGE_UP: 1208. switch(ptr->drawbridgemask & DB_UNDER) { 1209. case DB_MOAT: idx = S_pool; break; 1210. case DB_LAVA: idx = S_lava; break; 1211. case DB_ICE: idx = S_ice; break; 1212. case DB_FLOOR: idx = S_room; break; 1213. default: 1214. impossible("Strange db-under: %d", 1215. ptr->drawbridgemask & DB_UNDER); 1216. idx = S_room; /* something is better than nothing */ 1217. break; 1218. } 1219. break; 1220. case DRAWBRIDGE_DOWN: 1221. idx = (ptr->horizontal) ? S_hodbridge : S_vodbridge; 1222. break; 1223. default: 1224. impossible("back_to_glyph: unknown level type [ = %d ]",ptr->typ); 1225. idx = S_room; 1226. break; 1227. } 1228. 1229. return cmap_to_glyph(idx); 1230. } 1231. 1232. 1233. /* 1234. * swallow_to_glyph() 1235. * 1236. * Convert a monster number and a swallow location into the correct glyph. 1237. * If you don't want a patchwork monster while hallucinating, decide on 1238. * a random monster in swallowed() and don't use what_mon() here. 1239. */ 1240. static int 1241. swallow_to_glyph(mnum, loc) 1242. int mnum; 1243. int loc; 1244. { 1245. if (loc < S_sw_tl || S_sw_br < loc) { 1246. impossible("swallow_to_glyph: bad swallow location"); 1247. loc = S_sw_br; 1248. } 1249. return ((int) (what_mon(mnum)<<3) | (loc - S_sw_tl)) + GLYPH_SWALLOW_OFF; 1250. } 1251. 1252. 1253. 1254. /* 1255. * zapdir_to_glyph() 1256. * 1257. * Change the given zap direction and beam type into a glyph. Each beam 1258. * type has four glyphs, one for each of the symbols below. The order of 1259. * the zap symbols [0-3] as defined in rm.h are: 1260. * 1261. * | S_vbeam ( 0, 1) or ( 0,-1) 1262. * - S_hbeam ( 1, 0) or (-1, 0) 1263. * \ S_lslant ( 1, 1) or (-1,-1) 1264. * / S_rslant (-1, 1) or ( 1,-1) 1265. */ 1266. int 1267. zapdir_to_glyph(dx, dy, beam_type) 1268. register int dx, dy; 1269. int beam_type; 1270. { 1271. if (beam_type >= NUM_ZAP) { 1272. impossible("zapdir_to_glyph: illegal beam type"); 1273. beam_type = 0; 1274. } 1275. dx = (dx == dy) ? 2 : (dx && dy) ? 3 : dx ? 1 : 0; 1276. 1277. return ((int) ((beam_type << 2) | dx)) + GLYPH_ZAP_OFF; 1278. } 1279. 1280. 1281. /* 1282. * Utility routine for dowhatis() used to find out the glyph displayed at 1283. * the location. This isn't necessarily the same as the glyph in the levl 1284. * structure, so we must check the "third screen". 1285. */ 1286. int 1287. glyph_at(x, y) 1288. xchar x,y; 1289. { 1290. if(x < 0 || y < 0 || x >= COLNO || y >= ROWNO) 1291. return cmap_to_glyph(S_room); /* XXX */ 1292. return gbuf[y][x].glyph; 1293. } 1294. 1295. 1296. /* ------------------------------------------------------------------------- */ 1297. /* Wall Angle -------------------------------------------------------------- */ 1298. 1299. /*#define WA_VERBOSE /* give (x,y) locations for all "bad" spots */ 1300. 1301. #ifdef WA_VERBOSE 1302. 1303. static const char *FDECL(type_to_name, (int)); 1304. static void FDECL(error4, (int,int,int,int,int,int)); 1305. 1306. static int bad_count[MAX_TYPE]; /* count of positions flagged as bad */ 1307. static const char *type_names[MAX_TYPE] = { 1308. "STONE", "VWALL", "HWALL", "TLCORNER", 1309. "TRCORNER", "BLCORNER", "BRCORNER", "CROSSWALL", 1310. "TUWALL", "TDWALL", "TLWALL", "TRWALL", 1311. "DBWALL", "SDOOR", "SCORR", "POOL", 1312. "MOAT", "WATER", "DRAWBRIDGE_UP","LAVAPOOL", 1313. "DOOR", "CORR", "ROOM", "STAIRS", 1314. "LADDER", "FOUNTAIN", "THRONE", "SINK", 1315. "ALTAR", "ICE", "DRAWBRIDGE_DOWN","AIR", 1316. "CLOUD" 1317. }; 1318. 1319. 1320. static const char * 1321. type_to_name(type) 1322. int type; 1323. { 1324. return (type < 0 || type > MAX_TYPE) ? "unknown" : type_names[type]; 1325. } 1326. 1327. static void 1328. error4(x, y, a, b, c, dd) 1329. int x, y, a, b, c, dd; 1330. { 1331. pline("set_wall_state: %s @ (%d,%d) %s%s%s%s", 1332. type_to_name(levl[x][y].typ), x, y, 1333. a ? "1":"", b ? "2":"", c ? "3":"", dd ? "4":""); 1334. bad_count[levl[x][y].typ]++; 1335. } 1336. #endif /* WA_VERBOSE */ 1337. 1338. /* 1339. * Return 'which' if position is implies an unfinshed exterior. Return 1340. * zero otherwise. Unfinished implies outer area is rock or a corridor. 1341. * 1342. * Things that are ambigious: lava 1343. */ 1344. static int 1345. check_pos(x, y, which) 1346. int x, y, which; 1347. { 1348. int type; 1349. if (!isok(x,y)) return which; 1350. type = levl[x][y].typ; 1351. if (IS_ROCK(type) || type == CORR || type == SCORR) return which; 1352. return 0; 1353. } 1354. 1355. /* Return TRUE if more than one is non-zero. */ 1356. /*ARGSUSED*/ 1357. static boolean 1358. more_than_one(x, y, a, b, c) 1359. int x, y, a, b, c; 1360. { 1361. if ((a && (b|c)) || (b && (a|c)) || (c && (a|b))) { 1362. #ifdef WA_VERBOSE 1363. error4(x,y,a,b,c,0); 1364. #endif 1365. return TRUE; 1366. } 1367. return FALSE; 1368. } 1369. 1370. /* Return the wall mode for a T wall. */ 1371. static int 1372. set_twall(x0,y0, x1,y1, x2,y2, x3,y3) 1373. int x0,y0, x1,y1, x2,y2, x3,y3; 1374. { 1375. int wmode, is_1, is_2, is_3; 1376. 1377. is_1 = check_pos(x1, y1, WM_T_LONG); 1378. is_2 = check_pos(x2, y2, WM_T_BL); 1379. is_3 = check_pos(x3, y3, WM_T_BR); 1380. if (more_than_one(x0, y0, is_1, is_2, is_3)) { 1381. wmode = 0; 1382. } else { 1383. wmode = is_1 + is_2 + is_3; 1384. } 1385. return wmode; 1386. } 1387. 1388. /* Return wall mode for a horizontal or vertical wall. */ 1389. static int 1390. set_wall(x, y, horiz) 1391. int x, y, horiz; 1392. { 1393. int wmode, is_1, is_2; 1394. 1395. if (horiz) { 1396. is_1 = check_pos(x,y-1, WM_W_TOP); 1397. is_2 = check_pos(x,y+1, WM_W_BOTTOM); 1398. } else { 1399. is_1 = check_pos(x-1,y, WM_W_LEFT); 1400. is_2 = check_pos(x+1,y, WM_W_RIGHT); 1401. } 1402. if (more_than_one(x, y, is_1, is_2, 0)) { 1403. wmode = 0; 1404. } else { 1405. wmode = is_1 + is_2; 1406. } 1407. return wmode; 1408. } 1409. 1410. 1411. /* Return a wall mode for a corner wall. (x4,y4) is the "inner" position. */ 1412. static int 1413. set_corn(x1,y1, x2,y2, x3,y3, x4,y4) 1414. int x1, y1, x2, y2, x3, y3, x4, y4; 1415. { 1416. int wmode, is_1, is_2, is_3, is_4; 1417. 1418. is_1 = check_pos(x1, y1, 1); 1419. is_2 = check_pos(x2, y2, 1); 1420. is_3 = check_pos(x3, y3, 1); 1421. is_4 = check_pos(x4, y4, 1); /* inner location */ 1422. 1423. /* 1424. * All 4 should not be true. So if the inner location is rock, 1425. * use it. If all of the outer 3 are true, use outer. We currently 1426. * can't cover the case where only part of the outer is rock, so 1427. * we just say that all the walls are finished (if not overridden 1428. * by the inner section). 1429. */ 1430. if (is_4) { 1431. wmode = WM_C_INNER; 1432. } else if (is_1 && is_2 && is_3) 1433. wmode = WM_C_OUTER; 1434. else 1435. wmode = 0; /* finished walls on all sides */ 1436. 1437. return wmode; 1438. } 1439. 1440. /* Return mode for a crosswall. */ 1441. static int 1442. set_crosswall(x, y) 1443. int x, y; 1444. { 1445. int wmode, is_1, is_2, is_3, is_4; 1446. 1447. is_1 = check_pos(x-1, y-1, 1); 1448. is_2 = check_pos(x+1, y-1, 1); 1449. is_3 = check_pos(x+1, y+1, 1); 1450. is_4 = check_pos(x-1, y+1, 1); 1451. 1452. wmode = is_1+is_2+is_3+is_4; 1453. if (wmode > 1) { 1454. if (is_1 && is_3 && (is_2+is_4 == 0)) { 1455. wmode = WM_X_TLBR; 1456. } else if (is_2 && is_4 && (is_1+is_3 == 0)) { 1457. wmode = WM_X_BLTR; 1458. } else { 1459. #ifdef WA_VERBOSE 1460. error4(x,y,is_1,is_2,is_3,is_4); 1461. #endif 1462. wmode = 0; 1463. } 1464. } else if (is_1) 1465. wmode = WM_X_TL; 1466. else if (is_2) 1467. wmode = WM_X_TR; 1468. else if (is_3) 1469. wmode = WM_X_BR; 1470. else if (is_4) 1471. wmode = WM_X_BL; 1472. 1473. return wmode; 1474. } 1475. 1476. /* Called from mklev. Scan the level and set the wall modes. */ 1477. void 1478. set_wall_state() 1479. { 1480. int x, y; 1481. int wmode; 1482. struct rm *lev; 1483. 1484. #ifdef WA_VERBOSE 1485. for (x = 0; x < MAX_TYPE; x++) bad_count[x] = 0; 1486. #endif 1487. 1488. for (x = 0; x < COLNO; x++) 1489. for (lev = &levl[x][0], y = 0; y < ROWNO; y++, lev++) { 1490. switch (lev->typ) { 1491. case SDOOR: 1492. wmode = set_wall(x, y, (int) lev->horizontal); 1493. break; 1494. case VWALL: 1495. wmode = set_wall(x, y, 0); 1496. break; 1497. case HWALL: 1498. wmode = set_wall(x, y, 1); 1499. break; 1500. case TDWALL: 1501. wmode = set_twall(x,y, x,y-1, x-1,y+1, x+1,y+1); 1502. break; 1503. case TUWALL: 1504. wmode = set_twall(x,y, x,y+1, x+1,y-1, x-1,y-1); 1505. break; 1506. case TLWALL: 1507. wmode = set_twall(x,y, x+1,y, x-1,y-1, x-1,y+1); 1508. break; 1509. case TRWALL: 1510. wmode = set_twall(x,y, x-1,y, x+1,y+1, x+1,y-1); 1511. break; 1512. case TLCORNER: 1513. wmode = set_corn(x-1,y-1, x,y-1, x-1,y, x+1,y+1); 1514. break; 1515. case TRCORNER: 1516. wmode = set_corn(x,y-1, x+1,y-1, x+1,y, x-1,y+1); 1517. break; 1518. case BLCORNER: 1519. wmode = set_corn(x,y+1, x-1,y+1, x-1,y, x+1,y-1); 1520. break; 1521. case BRCORNER: 1522. wmode = set_corn(x+1,y, x+1,y+1, x,y+1, x-1,y-1); 1523. break; 1524. case CROSSWALL: 1525. wmode = set_crosswall(x, y); 1526. break; 1527. 1528. default: 1529. wmode = -1; /* don't set wall info */ 1530. break; 1531. } 1532. 1533. if (wmode >= 0) 1534. lev->wall_info = (lev->wall_info & ~WM_MASK) | wmode; 1535. } 1536. 1537. #ifdef WA_VERBOSE 1538. /* check if any bad positions found */ 1539. for (x = y = 0; x < MAX_TYPE; x++) 1540. if (bad_count[x]) { 1541. if (y == 0) { 1542. y = 1; /* only print once */ 1543. pline("set_wall_type: wall mode problems with: "); 1544. } 1545. pline("%s %d;", type_names[x], bad_count[x]); 1546. } 1547. #endif /* WA_VERBOSE */ 1548. } 1549. 1550. /* ------------------------------------------------------------------------- */ 1551. /* This matrix is used here and in vision.c. */ 1552. unsigned char seenv_matrix[3][3] = { {SV2, SV1, SV0}, 1553. {SV3, SVALL, SV7}, 1554. {SV4, SV5, SV6} }; 1555. 1556. #define sign(z) ((z) < 0 ? -1 : ((z) > 0 ? 1 : 0)) 1557. 1558. /* Set the seen vector of lev as if seen from (x0,y0) to (x,y). */ 1559. static void 1560. set_seenv(lev, x0, y0, x, y) 1561. struct rm *lev; 1562. int x0, y0, x, y; /* from, to */ 1563. { 1564. int dx = x-x0, dy = y0-y; 1565. lev->seenv |= seenv_matrix[sign(dy)+1][sign(dx)+1]; 1566. } 1567. 1568. /* ------------------------------------------------------------------------- */ 1569. 1570. /* T wall types, one for each row in wall_matrix[][]. */ 1571. #define T_d 0 1572. #define T_l 1 1573. #define T_u 2 1574. #define T_r 3 1575. 1576. /* 1577. * These are the column names of wall_matrix[][]. They are the "results" 1578. * of a tdwall pattern match. All T walls are rotated so they become 1579. * a tdwall. Then we do a single pattern match, but return the 1580. * correct result for the original wall by using different rows for 1581. * each of the wall types. 1582. */ 1583. #define T_stone 0 1584. #define T_tlcorn 1 1585. #define T_trcorn 2 1586. #define T_hwall 3 1587. #define T_tdwall 4 1588. 1589. static const int wall_matrix[4][5] = { 1590. { S_stone, S_tlcorn, S_trcorn, S_hwall, S_tdwall }, /* tdwall */ 1591. { S_stone, S_trcorn, S_brcorn, S_vwall, S_tlwall }, /* tlwall */ 1592. { S_stone, S_brcorn, S_blcorn, S_hwall, S_tuwall }, /* tuwall */ 1593. { S_stone, S_blcorn, S_tlcorn, S_vwall, S_trwall }, /* trwall */ 1594. }; 1595. 1596. 1597. /* Cross wall types, one for each "solid" quarter. Rows of cross_matrix[][]. */ 1598. #define C_bl 0 1599. #define C_tl 1 1600. #define C_tr 2 1601. #define C_br 3 1602. 1603. /* 1604. * These are the column names for cross_matrix[][]. They express results 1605. * in C_br (bottom right) terms. All crosswalls with a single solid 1606. * quarter are rotated so the solid section is at the bottom right. 1607. * We pattern match on that, but return the correct result depending 1608. * on which row we'ere looking at. 1609. */ 1610. #define C_trcorn 0 1611. #define C_brcorn 1 1612. #define C_blcorn 2 1613. #define C_tlwall 3 1614. #define C_tuwall 4 1615. #define C_crwall 5 1616. 1617. static const int cross_matrix[4][6] = { 1618. { S_brcorn, S_blcorn, S_tlcorn, S_tuwall, S_trwall, S_crwall }, 1619. { S_blcorn, S_tlcorn, S_trcorn, S_trwall, S_tdwall, S_crwall }, 1620. { S_tlcorn, S_trcorn, S_brcorn, S_tdwall, S_tlwall, S_crwall }, 1621. { S_trcorn, S_brcorn, S_blcorn, S_tlwall, S_tuwall, S_crwall }, 1622. }; 1623. 1624. 1625. /* Print out a T wall warning and all interesting info. */ 1626. static void 1627. t_warn(lev) 1628. struct rm *lev; 1629. { 1630. static const char *warn_str = "wall_angle: %s: case %d: seenv = 0x%x"; 1631. const char *wname; 1632. 1633. if (lev->typ == TUWALL) wname = "tuwall"; 1634. else if (lev->typ == TLWALL) wname = "tlwall"; 1635. else if (lev->typ == TRWALL) wname = "trwall"; 1636. else if (lev->typ == TDWALL) wname = "tdwall"; 1637. else wname = "unknown"; 1638. impossible(warn_str, wname, lev->wall_info & WM_MASK, 1639. (unsigned int) lev->seenv); 1640. } 1641. 1642. 1643. /* 1644. * Return the correct graphics character index using wall type, wall mode, 1645. * and the seen vector. It is expected that seenv is non zero. 1646. * 1647. * All T-wall vectors are rotated to be TDWALL. All single crosswall 1648. * blocks are rotated to bottom right. All double crosswall are rotated 1649. * to W_X_BLTR. All results are converted back. 1650. * 1651. * The only way to understand this is to take out pen and paper and 1652. * draw diagrams. See rm.h for more details on the wall modes and 1653. * seen vector (SV). 1654. */ 1655. static int 1656. wall_angle(lev) 1657. struct rm *lev; 1658. { 1659. register unsigned int seenv = lev->seenv & 0xff; 1660. const int *row; 1661. int col, idx; 1662. 1663. #define only(sv, bits) (((sv) & (bits)) && ! ((sv) & ~(bits))) 1664. switch (lev->typ) { 1665. case TUWALL: 1666. row = wall_matrix[T_u]; 1667. seenv = (seenv >> 4 | seenv << 4) & 0xff;/* rotate to tdwall */ 1668. goto do_twall; 1669. case TLWALL: 1670. row = wall_matrix[T_l]; 1671. seenv = (seenv >> 2 | seenv << 6) & 0xff;/* rotate to tdwall */ 1672. goto do_twall; 1673. case TRWALL: 1674. row = wall_matrix[T_r]; 1675. seenv = (seenv >> 6 | seenv << 2) & 0xff;/* rotate to tdwall */ 1676. goto do_twall; 1677. case TDWALL: 1678. row = wall_matrix[T_d]; 1679. do_twall: 1680. switch (lev->wall_info & WM_MASK) { 1681. case 0: 1682. if (seenv == SV4) { 1683. col = T_tlcorn; 1684. } else if (seenv == SV6) { 1685. col = T_trcorn; 1686. } else if (seenv & (SV3|SV5|SV7) || 1687. ((seenv & SV4) && (seenv & SV6))) { 1688. col = T_tdwall; 1689. } else if (seenv & (SV0|SV1|SV2)) { 1690. col = (seenv & (SV4|SV6) ? T_tdwall : T_hwall); 1691. } else { 1692. t_warn(lev); 1693. col = T_stone; 1694. } 1695. break; 1696. case WM_T_LONG: 1697. if (seenv & (SV3|SV4) && !(seenv & (SV5|SV6|SV7))) { 1698. col = T_tlcorn; 1699. } else if (seenv&(SV6|SV7) && !(seenv&(SV3|SV4|SV5))) { 1700. col = T_trcorn; 1701. } else if ((seenv & SV5) || 1702. ((seenv & (SV3|SV4)) && (seenv & (SV6|SV7)))) { 1703. col = T_tdwall; 1704. } else { 1705. /* only SV0|SV1|SV2 */ 1706. if (! only(seenv, SV0|SV1|SV2) ) 1707. t_warn(lev); 1708. col = T_stone; 1709. } 1710. break; 1711. case WM_T_BL: 1712. #if 0 /* older method, fixed */ 1713. if (only(seenv, SV4|SV5)) { 1714. col = T_tlcorn; 1715. } else if ((seenv & (SV0|SV1|SV2)) && 1716. only(seenv, SV0|SV1|SV2|SV6|SV7)) { 1717. col = T_hwall; 1718. } else if (seenv & SV3 || 1719. ((seenv & (SV0|SV1|SV2)) && (seenv & (SV4|SV5)))) { 1720. col = T_tdwall; 1721. } else { 1722. if (seenv != SV6) 1723. t_warn(lev); 1724. col = T_stone; 1725. } 1726. #endif /* 0 */ 1727. if (only(seenv, SV4|SV5)) 1728. col = T_tlcorn; 1729. else if ((seenv & (SV0|SV1|SV2|SV7)) && 1730. !(seenv & (SV3|SV4|SV5))) 1731. col = T_hwall; 1732. else if (only(seenv, SV6)) 1733. col = T_stone; 1734. else 1735. col = T_tdwall; 1736. break; 1737. case WM_T_BR: 1738. #if 0 /* older method, fixed */ 1739. if (only(seenv, SV5|SV6)) { 1740. col = T_trcorn; 1741. } else if ((seenv & (SV0|SV1|SV2)) && 1742. only(seenv, SV0|SV1|SV2|SV3|SV4)) { 1743. col = T_hwall; 1744. } else if (seenv & SV7 || 1745. ((seenv & (SV0|SV1|SV2)) && (seenv & (SV5|SV6)))) { 1746. col = T_tdwall; 1747. } else { 1748. if (seenv != SV4) 1749. t_warn(lev); 1750. col = T_stone; 1751. } 1752. #endif /* 0 */ 1753. if (only(seenv, SV5|SV6)) 1754. col = T_trcorn; 1755. else if ((seenv & (SV0|SV1|SV2|SV3)) && 1756. !(seenv & (SV5|SV6|SV7))) 1757. col = T_hwall; 1758. else if (only(seenv, SV4)) 1759. col = T_stone; 1760. else 1761. col = T_tdwall; 1762. 1763. break; 1764. default: 1765. impossible("wall_angle: unknown T wall mode %d", 1766. lev->wall_info & WM_MASK); 1767. col = T_stone; 1768. break; 1769. } 1770. idx = row[col]; 1771. break; 1772. 1773. case SDOOR: 1774. if (lev->horizontal) goto horiz; 1775. /* fall through */ 1776. case VWALL: 1777. switch (lev->wall_info & WM_MASK) { 1778. case 0: idx = seenv ? S_vwall : S_stone; break; 1779. case 1: idx = seenv & (SV1|SV2|SV3|SV4|SV5) ? S_vwall : 1780. S_stone; 1781. break; 1782. case 2: idx = seenv & (SV0|SV1|SV5|SV6|SV7) ? S_vwall : 1783. S_stone; 1784. break; 1785. default: 1786. impossible("wall_angle: unknown vwall mode %d", 1787. lev->wall_info & WM_MASK); 1788. idx = S_stone; 1789. break; 1790. } 1791. break; 1792. 1793. case HWALL: 1794. horiz: 1795. switch (lev->wall_info & WM_MASK) { 1796. case 0: idx = seenv ? S_hwall : S_stone; break; 1797. case 1: idx = seenv & (SV3|SV4|SV5|SV6|SV7) ? S_hwall : 1798. S_stone; 1799. break; 1800. case 2: idx = seenv & (SV0|SV1|SV2|SV3|SV7) ? S_hwall : 1801. S_stone; 1802. break; 1803. default: 1804. impossible("wall_angle: unknown hwall mode %d", 1805. lev->wall_info & WM_MASK); 1806. idx = S_stone; 1807. break; 1808. } 1809. break; 1810. 1811. #define set_corner(idx, lev, which, outer, inner, name) \ 1812. switch ((lev)->wall_info & WM_MASK) { \ 1813. case 0: idx = which; break; \ 1814. case WM_C_OUTER: idx = seenv & (outer) ? which : S_stone; break; \ 1815. case WM_C_INNER: idx = seenv & ~(inner) ? which : S_stone; break; \ 1816. default: \ 1817. impossible("wall_angle: unknown %s mode %d", name, \ 1818. (lev)->wall_info & WM_MASK); \ 1819. idx = S_stone; \ 1820. break; \ 1821. } 1822. 1823. case TLCORNER: 1824. set_corner(idx, lev, S_tlcorn, (SV3|SV4|SV5), SV4, "tlcorn"); 1825. break; 1826. case TRCORNER: 1827. set_corner(idx, lev, S_trcorn, (SV5|SV6|SV7), SV6, "trcorn"); 1828. break; 1829. case BLCORNER: 1830. set_corner(idx, lev, S_blcorn, (SV1|SV2|SV3), SV2, "blcorn"); 1831. break; 1832. case BRCORNER: 1833. set_corner(idx, lev, S_brcorn, (SV7|SV0|SV1), SV0, "brcorn"); 1834. break; 1835. 1836. 1837. case CROSSWALL: 1838. switch (lev->wall_info & WM_MASK) { 1839. case 0: 1840. if (seenv == SV0) 1841. idx = S_brcorn; 1842. else if (seenv == SV2) 1843. idx = S_blcorn; 1844. else if (seenv == SV4) 1845. idx = S_tlcorn; 1846. else if (seenv == SV6) 1847. idx = S_trcorn; 1848. else if (!(seenv & ~(SV0|SV1|SV2)) && 1849. (seenv & SV1 || seenv == (SV0|SV2))) 1850. idx = S_tuwall; 1851. else if (!(seenv & ~(SV2|SV3|SV4)) && 1852. (seenv & SV3 || seenv == (SV2|SV4))) 1853. idx = S_trwall; 1854. else if (!(seenv & ~(SV4|SV5|SV6)) && 1855. (seenv & SV5 || seenv == (SV4|SV6))) 1856. idx = S_tdwall; 1857. else if (!(seenv & ~(SV0|SV6|SV7)) && 1858. (seenv & SV7 || seenv == (SV0|SV6))) 1859. idx = S_tlwall; 1860. else 1861. idx = S_crwall; 1862. break; 1863. 1864. case WM_X_TL: 1865. row = cross_matrix[C_tl]; 1866. seenv = (seenv >> 4 | seenv << 4) & 0xff; 1867. goto do_crwall; 1868. case WM_X_TR: 1869. row = cross_matrix[C_tr]; 1870. seenv = (seenv >> 6 | seenv << 2) & 0xff; 1871. goto do_crwall; 1872. case WM_X_BL: 1873. row = cross_matrix[C_bl]; 1874. seenv = (seenv >> 2 | seenv << 6) & 0xff; 1875. goto do_crwall; 1876. case WM_X_BR: 1877. row = cross_matrix[C_br]; 1878. do_crwall: 1879. if (seenv == SV4) 1880. idx = S_stone; 1881. else { 1882. seenv = seenv & ~SV4; /* strip SV4 */ 1883. if (seenv == SV0) { 1884. col = C_brcorn; 1885. } else if (seenv & (SV2|SV3)) { 1886. if (seenv & (SV5|SV6|SV7)) 1887. col = C_crwall; 1888. else if (seenv & (SV0|SV1)) 1889. col = C_tuwall; 1890. else 1891. col = C_blcorn; 1892. } else if (seenv & (SV5|SV6)) { 1893. if (seenv & (SV1|SV2|SV3)) 1894. col = C_crwall; 1895. else if (seenv & (SV0|SV7)) 1896. col = C_tlwall; 1897. else 1898. col = C_trcorn; 1899. } else if (seenv & SV1) { 1900. col = seenv & SV7 ? C_crwall : C_tuwall; 1901. } else if (seenv & SV7) { 1902. col = seenv & SV1 ? C_crwall : C_tlwall; 1903. } else { 1904. impossible( 1905. "wall_angle: bottom of crwall check"); 1906. col = C_crwall; 1907. } 1908. 1909. idx = row[col]; 1910. } 1911. break; 1912. 1913. case WM_X_TLBR: 1914. if ( only(seenv, SV1|SV2|SV3) ) 1915. idx = S_blcorn; 1916. else if ( only(seenv, SV5|SV6|SV7) ) 1917. idx = S_trcorn; 1918. else if ( only(seenv, SV0|SV4) ) 1919. idx = S_stone; 1920. else 1921. idx = S_crwall; 1922. break; 1923. 1924. case WM_X_BLTR: 1925. if ( only(seenv, SV0|SV1|SV7) ) 1926. idx = S_brcorn; 1927. else if ( only(seenv, SV3|SV4|SV5) ) 1928. idx = S_tlcorn; 1929. else if ( only(seenv, SV2|SV6) ) 1930. idx = S_stone; 1931. else 1932. idx = S_crwall; 1933. break; 1934. 1935. default: 1936. impossible("wall_angle: unknown crosswall mode"); 1937. idx = S_stone; 1938. break; 1939. } 1940. break; 1941. 1942. default: 1943. impossible("wall_angle: unexpected wall type %d", lev->typ); 1944. idx = S_stone; 1945. } 1946. return idx; 1947. } 1948. 1949. /*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