Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/display.c

2,032pages on
this wiki
Talk0

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.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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*/

Around Wikia's network

Random Wiki