~ubuntu-branches/ubuntu/saucy/nethack/saucy

« back to all changes in this revision

Viewing changes to .pc/0013-93_enh_dump.dpatch-by-Tom-Friedetzky-Jukka-Lahtinen-.patch/src/display.c

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng, Bernhard R. Link, Vincent Cheng
  • Date: 2012-06-11 00:47:38 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120611004738-3fy8b3wi0j45y2oq
Tags: 3.4.3-14
* Team upload.

[ Bernhard R. Link ]
* switch to "3.0 (quilt)"
* bump Standards-Version
* modernize debian/rules:
- use dpkg-buildflags
- support build-arch/-indep
- make parallel safe
- don't avoid make errors
* add patch so it can compile with -Werror=format-security
* drop no longer needed patches (-qt and -gnome are gone)
* don't use /dev/null as install template (Closes: 644647)
* drop nethack-common menu (both -console and -x11 have one)

[ Vincent Cheng ]
* Adopt package. (Closes: #673584)
  - Change Maintainer to Debian Games Team.
  - Add myself to Uploaders.
* Modify 0006-Common-config.h-for-all-binary-packages.patch to enable
  AUTOPICKUP_EXCEPTIONS. (Closes: #329318)
* Modify 0011-Pasi-Kallinen-s-patch-to-add-colors-to-inventory-ite.patch
  and 0017-Debian-and-Linux-specifics-defined-in-unixconf.h.patch; add
  0021-fix-kfreebsd-ftbfs.patch to fix FTBFS on kfreebsd.
* Convert debian/copyright to DEP-5 machine-readable format.
* Use dh_lintian to install overrides instead of manually installing them
  in debian/rules.
* Add watch file.
* Add Homepage field in debian/control.
* Add Vcs-* fields in debian/control.

Show diffs side-by-side

added added

removed removed

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