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