Source:SLASH'EM 0.0.7E7F2/display.c

Below is the full text to display.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/display.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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